diff --git a/csharp/ql/src/API Abuse/Dispose.qll b/csharp/ql/src/API Abuse/Dispose.qll index 508b8b35f19..0e3d75e012c 100644 --- a/csharp/ql/src/API Abuse/Dispose.qll +++ b/csharp/ql/src/API Abuse/Dispose.qll @@ -4,28 +4,18 @@ private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.frameworks.system.web.UI class DisposableType extends RefType { - DisposableType() { - this.getABaseType+() instanceof SystemIDisposableInterface - } + DisposableType() { this.getABaseType+() instanceof SystemIDisposableInterface } } class DisposableField extends Field { - DisposableField() { - this.getType() instanceof DisposableType - } + DisposableField() { this.getType() instanceof DisposableType } } class WebControl extends RefType { - WebControl() { - this.getBaseClass*() instanceof SystemWebUIControlClass - } + WebControl() { this.getBaseClass*() instanceof SystemWebUIControlClass } } -class WebPage extends RefType { - WebPage() { - this.getBaseClass*() instanceof SystemWebUIPageClass - } -} +class WebPage extends RefType { WebPage() { this.getBaseClass*() instanceof SystemWebUIPageClass } } /** * Holds if `f` is an auto-disposed web control. @@ -37,15 +27,13 @@ class WebPage extends RefType { * `UnloadRecursive()`. */ predicate isAutoDisposedWebControl(Field f) { - f.getType() instanceof WebControl - and + f.getType() instanceof WebControl and f.getDeclaringType() = any(RefType t | - t instanceof WebControl or - t instanceof WebPage - ) + t instanceof WebControl or + t instanceof WebPage + ) } - /** * An object creation that creates an `IDisposable` instance into the local scope. */ @@ -56,13 +44,13 @@ class LocalScopeDisposableCreation extends Call { // Type extends IDisposable t instanceof DisposableType and // Within function, not field or instance initializer - exists(this.getEnclosingCallable()) | + exists(this.getEnclosingCallable()) + | // Either an ordinary object creation this instanceof ObjectCreation or // Or a creation using a factory method - exists(Method create | - this.getTarget() = create | + exists(Method create | this.getTarget() = create | create.hasName("Create") and create.isStatic() and create.getDeclaringType().getSourceDeclaration() = t.getSourceDeclaration() @@ -74,20 +62,17 @@ class LocalScopeDisposableCreation extends Call { * Gets an expression that, if it is disposed of, will imply that the object * created by this creation is disposed of as well. */ - Expr getADisposeTarget() { - result = getADisposeTarget0().asExpr() - } + Expr getADisposeTarget() { result = getADisposeTarget0().asExpr() } private DataFlow::Node getADisposeTarget0() { result = exprNode(this) or - exists(DataFlow::Node mid | - mid = this.getADisposeTarget0() | + exists(DataFlow::Node mid | mid = this.getADisposeTarget0() | localFlowStep(mid, result) or result.asExpr() = any(LocalScopeDisposableCreation other | - other.getAnArgument() = mid.asExpr() - ) + other.getAnArgument() = mid.asExpr() + ) ) } } diff --git a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll index 8621c81f26c..21e2e29c2eb 100644 --- a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll +++ b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstants.qll @@ -3,45 +3,188 @@ import semmle.code.csharp.commons.GeneratedCode import semmle.code.csharp.frameworks.System /* - * * Counting nontrivial literal occurrences - * */ private predicate trivialPositiveIntValue(string s) { - s="0" or s="1" or s="2" or s="3" or s="4" or s="5" or s="6" or s="7" or s="8" or - s="9" or s="10" or s="11" or s="12" or s="13" or s="14" or s="15" or s="16" or s="17" or - s="18" or s="19" or s="20" - - or - - s="16" or s="32" or s="64" or s="128" or s="256" or s="512" or s="1024" or - s="2048" or s="4096" or s="16384" or s="32768" or s="65536" or - s="1048576" or s="2147483648" or s="4294967296" - - or - - s="15" or s="31" or s="63" or s="127" or s="255" or s="511" or s="1023" or - s="2047" or s="4095" or s="16383" or s="32767" or s="65535" or - s="1048577" or s="2147483647" or s="4294967295" - - or - - s = "0x00000001" or s = "0x00000002" or s = "0x00000004" or s = "0x00000008" or s = "0x00000010" or s = "0x00000020" or s = "0x00000040" or s = "0x00000080" or s = "0x00000100" or s = "0x00000200" or s = "0x00000400" or s = "0x00000800" or s = "0x00001000" or s = "0x00002000" or s = "0x00004000" or s = "0x00008000" or s = "0x00010000" or s = "0x00020000" or s = "0x00040000" or s = "0x00080000" or s = "0x00100000" or s = "0x00200000" or s = "0x00400000" or s = "0x00800000" or s = "0x01000000" or s = "0x02000000" or s = "0x04000000" or s = "0x08000000" or s = "0x10000000" or s = "0x20000000" or s = "0x40000000" or s = "0x80000000" or - s = "0x00000001" or s = "0x00000003" or s = "0x00000007" or s = "0x0000000f" or s = "0x0000001f" or s = "0x0000003f" or s = "0x0000007f" or s = "0x000000ff" or s = "0x000001ff" or s = "0x000003ff" or s = "0x000007ff" or s = "0x00000fff" or s = "0x00001fff" or s = "0x00003fff" or s = "0x00007fff" or s = "0x0000ffff" or s = "0x0001ffff" or s = "0x0003ffff" or s = "0x0007ffff" or s = "0x000fffff" or s = "0x001fffff" or s = "0x003fffff" or s = "0x007fffff" or s = "0x00ffffff" or s = "0x01ffffff" or s = "0x03ffffff" or s = "0x07ffffff" or s = "0x0fffffff" or s = "0x1fffffff" or s = "0x3fffffff" or s = "0x7fffffff" or s = "0xffffffff" or - s = "0x0001" or s = "0x0002" or s = "0x0004" or s = "0x0008" or s = "0x0010" or s = "0x0020" or s = "0x0040" or s = "0x0080" or s = "0x0100" or s = "0x0200" or s = "0x0400" or s = "0x0800" or s = "0x1000" or s = "0x2000" or s = "0x4000" or s = "0x8000" or - s = "0x0001" or s = "0x0003" or s = "0x0007" or s = "0x000f" or s = "0x001f" or s = "0x003f" or s = "0x007f" or s = "0x00ff" or s = "0x01ff" or s = "0x03ff" or s = "0x07ff" or s = "0x0fff" or s = "0x1fff" or s = "0x3fff" or s = "0x7fff" or s = "0xffff" or - s = "0x01" or s = "0x02" or s = "0x04" or s = "0x08" or s = "0x10" or s = "0x20" or s = "0x40" or s = "0x80" or - s = "0x01" or s = "0x03" or s = "0x07" or s = "0x0f" or s = "0x1f" or s = "0x3f" or s = "0x7f" or s = "0xff" or - s = "0x00" - - or - - s = "10" or s = "100" or s = "1000" or s = "10000" or s = "100000" or s = "1000000" or s = "10000000" or s = "100000000" or s = "1000000000" + s = "0" or + s = "1" or + s = "2" or + s = "3" or + s = "4" or + s = "5" or + s = "6" or + s = "7" or + s = "8" or + s = "9" or + s = "10" or + s = "11" or + s = "12" or + s = "13" or + s = "14" or + s = "15" or + s = "16" or + s = "17" or + s = "18" or + s = "19" or + s = "20" or + s = "16" or + s = "32" or + s = "64" or + s = "128" or + s = "256" or + s = "512" or + s = "1024" or + s = "2048" or + s = "4096" or + s = "16384" or + s = "32768" or + s = "65536" or + s = "1048576" or + s = "2147483648" or + s = "4294967296" or + s = "15" or + s = "31" or + s = "63" or + s = "127" or + s = "255" or + s = "511" or + s = "1023" or + s = "2047" or + s = "4095" or + s = "16383" or + s = "32767" or + s = "65535" or + s = "1048577" or + s = "2147483647" or + s = "4294967295" or + s = "0x00000001" or + s = "0x00000002" or + s = "0x00000004" or + s = "0x00000008" or + s = "0x00000010" or + s = "0x00000020" or + s = "0x00000040" or + s = "0x00000080" or + s = "0x00000100" or + s = "0x00000200" or + s = "0x00000400" or + s = "0x00000800" or + s = "0x00001000" or + s = "0x00002000" or + s = "0x00004000" or + s = "0x00008000" or + s = "0x00010000" or + s = "0x00020000" or + s = "0x00040000" or + s = "0x00080000" or + s = "0x00100000" or + s = "0x00200000" or + s = "0x00400000" or + s = "0x00800000" or + s = "0x01000000" or + s = "0x02000000" or + s = "0x04000000" or + s = "0x08000000" or + s = "0x10000000" or + s = "0x20000000" or + s = "0x40000000" or + s = "0x80000000" or + s = "0x00000001" or + s = "0x00000003" or + s = "0x00000007" or + s = "0x0000000f" or + s = "0x0000001f" or + s = "0x0000003f" or + s = "0x0000007f" or + s = "0x000000ff" or + s = "0x000001ff" or + s = "0x000003ff" or + s = "0x000007ff" or + s = "0x00000fff" or + s = "0x00001fff" or + s = "0x00003fff" or + s = "0x00007fff" or + s = "0x0000ffff" or + s = "0x0001ffff" or + s = "0x0003ffff" or + s = "0x0007ffff" or + s = "0x000fffff" or + s = "0x001fffff" or + s = "0x003fffff" or + s = "0x007fffff" or + s = "0x00ffffff" or + s = "0x01ffffff" or + s = "0x03ffffff" or + s = "0x07ffffff" or + s = "0x0fffffff" or + s = "0x1fffffff" or + s = "0x3fffffff" or + s = "0x7fffffff" or + s = "0xffffffff" or + s = "0x0001" or + s = "0x0002" or + s = "0x0004" or + s = "0x0008" or + s = "0x0010" or + s = "0x0020" or + s = "0x0040" or + s = "0x0080" or + s = "0x0100" or + s = "0x0200" or + s = "0x0400" or + s = "0x0800" or + s = "0x1000" or + s = "0x2000" or + s = "0x4000" or + s = "0x8000" or + s = "0x0001" or + s = "0x0003" or + s = "0x0007" or + s = "0x000f" or + s = "0x001f" or + s = "0x003f" or + s = "0x007f" or + s = "0x00ff" or + s = "0x01ff" or + s = "0x03ff" or + s = "0x07ff" or + s = "0x0fff" or + s = "0x1fff" or + s = "0x3fff" or + s = "0x7fff" or + s = "0xffff" or + s = "0x01" or + s = "0x02" or + s = "0x04" or + s = "0x08" or + s = "0x10" or + s = "0x20" or + s = "0x40" or + s = "0x80" or + s = "0x01" or + s = "0x03" or + s = "0x07" or + s = "0x0f" or + s = "0x1f" or + s = "0x3f" or + s = "0x7f" or + s = "0xff" or + s = "0x00" or + s = "10" or + s = "100" or + s = "1000" or + s = "10000" or + s = "100000" or + s = "1000000" or + s = "10000000" or + s = "100000000" or + s = "1000000000" } private predicate trivialIntValue(string s) { - trivialPositiveIntValue(s) or + trivialPositiveIntValue(s) + or exists(string pos | trivialPositiveIntValue(pos) and s = "-" + pos) } @@ -50,7 +193,15 @@ private predicate intTrivial(Literal lit) { } private predicate powerOfTen(float f) { - f = 10 or f = 100 or f = 1000 or f = 10000 or f = 100000 or f = 1000000 or f = 10000000 or f = 100000000 or f = 1000000000 + f = 10 or + f = 100 or + f = 1000 or + f = 10000 or + f = 100000 or + f = 1000000 or + f = 10000000 or + f = 100000000 or + f = 1000000000 } private predicate floatTrivial(Literal lit) { @@ -59,16 +210,12 @@ private predicate floatTrivial(Literal lit) { lit.getValue() = value and f = value.toFloat() and (f.abs() <= 20.0 or powerOfTen(f)) - ) + ) } -private predicate stringTrivial(StringLiteral lit) { - lit.getValue().length() < 8 -} +private predicate stringTrivial(StringLiteral lit) { lit.getValue().length() < 8 } -private predicate small(Literal lit) { - lit.getValue().length() <= 1 -} +private predicate small(Literal lit) { lit.getValue().length() <= 1 } private predicate trivial(Literal lit) { intTrivial(lit) or @@ -81,10 +228,8 @@ private predicate trivial(Literal lit) { } private predicate literalIsConstantInitializer(Literal literal, string value, Field f) { - literal.getValue() = value - and - literal = f.getInitializer().stripCasts() - and + literal.getValue() = value and + literal = f.getInitializer().stripCasts() and ( f.isReadOnly() and f.isStatic() or @@ -93,19 +238,16 @@ private predicate literalIsConstantInitializer(Literal literal, string value, Fi } private predicate literalInArrayInitializer(Literal literal) { - exists(ArrayInitializer arrayInit | - arrayInit.getAnElement().stripCasts() = literal - ) + exists(ArrayInitializer arrayInit | arrayInit.getAnElement().stripCasts() = literal) } -private predicate literalInAttribute(Literal literal) { - literal.getParent+() instanceof Attribute -} +private predicate literalInAttribute(Literal literal) { literal.getParent+() instanceof Attribute } private predicate literalInGetHashCode(Literal literal) { exists(Method m, Method getHashCode | m = literal.getEnclosingCallable() and - getHashCode = any(SystemObjectClass c).getGetHashCodeMethod() | + getHashCode = any(SystemObjectClass c).getGetHashCodeMethod() + | m = getHashCode.getAnOverrider*() ) } @@ -121,8 +263,10 @@ private predicate relevantLiteral(Literal literal, string value) { } private predicate valueOccurrenceCount(string value, int n) { - n = strictcount(Location loc | exists(Literal lit | relevantLiteral(lit, value) | lit.getLocation()=loc)) - and n > 20 + n = strictcount(Location loc | + exists(Literal lit | relevantLiteral(lit, value) | lit.getLocation() = loc) + ) and + n > 20 } private predicate occurenceCount(Literal lit, string value, int n) { @@ -131,24 +275,23 @@ private predicate occurenceCount(Literal lit, string value, int n) { relevantLiteral(lit, value) } - /* - * * Literals repeated frequently - * */ private predicate check(Literal lit, string value, int n, File f) { // Check that the literal is nontrivial not trivial(lit) and // Check that it is repeated a number of times - occurenceCount(lit, value, n) and n > 20 and + occurenceCount(lit, value, n) and + n > 20 and f = lit.getFile() } private predicate checkWithFileCount(string value, int overallCount, int fileCount, File f) { - fileCount = strictcount(Location loc | exists(Literal lit | - check(lit, value, overallCount, f) | lit.getLocation()=loc) ) + fileCount = strictcount(Location loc | + exists(Literal lit | check(lit, value, overallCount, f) | lit.getLocation() = loc) + ) } private predicate start(Literal lit, int startLine) { @@ -164,32 +307,34 @@ private predicate firstOccurrence(Literal lit, string value, int n) { check(lit2, value, n, f) and start(lit, start1) and start(lit2, start2) and - start2 < start1) + start2 < start1 ) + ) } -private predicate isFloat(Literal lit) { - lit.getType() instanceof FloatingPointType -} +private predicate isFloat(Literal lit) { lit.getType() instanceof FloatingPointType } predicate isNumber(Literal lit) { - lit.getType() instanceof IntegralType - or isFloat(lit) + lit.getType() instanceof IntegralType or + isFloat(lit) } predicate magicConstant(Literal e, string msg) { - exists(string value, int n | firstOccurrence(e, value, n) - and msg = "Magic constant: literal '" + value + "' is repeated " + n.toString() + " times and should be encapsulated in a constant.") + exists(string value, int n | + firstOccurrence(e, value, n) and + msg = "Magic constant: literal '" + value + "' is repeated " + n.toString() + + " times and should be encapsulated in a constant." + ) } /* - * * Literals where there is a defined constant with the same value - * */ private predicate relevantField(Field f, string value) { - exists(Literal lit | not trivial(lit) and value = lit.getValue() and literalIsConstantInitializer(lit, value, f)) + exists(Literal lit | + not trivial(lit) and value = lit.getValue() and literalIsConstantInitializer(lit, value, f) + ) } private predicate relevantDeclaration(Declaration d, Literal lit, string value) { @@ -207,44 +352,43 @@ private predicate hasAccessModifier(Field field) { //Default accessibility rules http://msdn.microsoft.com/en-us/library/ba0a1yw2%28v=vs.71%29.aspx private predicate isPublic(Field field) { - field.isPublic() or - (not hasAccessModifier(field) and (field.getDeclaringType() instanceof Interface or field.getDeclaringType() instanceof Enum)) + field.isPublic() + or + not hasAccessModifier(field) and + (field.getDeclaringType() instanceof Interface or field.getDeclaringType() instanceof Enum) } private predicate isPrivate(Field field) { - field.isPrivate() or - (not hasAccessModifier(field) and (field.getDeclaringType() instanceof Class or field.getDeclaringType() instanceof Struct)) + field.isPrivate() + or + not hasAccessModifier(field) and + (field.getDeclaringType() instanceof Class or field.getDeclaringType() instanceof Struct) } private predicate isVisible(Field field, string value, Declaration fromDeclaration) { //public - ( - relevantField(field, value) and - field.getDeclaringType().isPublic() and - isPublic(field) and - relevantDeclaration(fromDeclaration, _, value) - ) + relevantField(field, value) and + field.getDeclaringType().isPublic() and + isPublic(field) and + relevantDeclaration(fromDeclaration, _, value) or //in same class - ( - relevantField(field, value) and - exists(RefType t | - t = field.getDeclaringType() and - t = fromDeclaration.getDeclaringType()) - and relevantDeclaration(fromDeclaration, _, value) - ) + relevantField(field, value) and + exists(RefType t | + t = field.getDeclaringType() and + t = fromDeclaration.getDeclaringType() + ) and + relevantDeclaration(fromDeclaration, _, value) or //in subclass and not private - ( - relevantField(field, value) and - not isPrivate(field) and - exists(RefType sup, RefType sub | - sup = field.getDeclaringType() and - sub.getABaseType+() = sup and - sub = fromDeclaration.getDeclaringType() - ) and - relevantDeclaration(fromDeclaration, _, value) - ) + relevantField(field, value) and + not isPrivate(field) and + exists(RefType sup, RefType sub | + sup = field.getDeclaringType() and + sub.getABaseType+() = sup and + sub = fromDeclaration.getDeclaringType() + ) and + relevantDeclaration(fromDeclaration, _, value) //internal and in same assembly //TODO: internal (I don't think we can do this yet, as we don't associate elements in source to assemblies) } @@ -252,24 +396,23 @@ private predicate isVisible(Field field, string value, Declaration fromDeclarati /** * Literal.getValue() restricted to literals which aren't used as constant initialisers. */ -private string magicLiteralValue(Literal l) { - relevantLiteral(l, result) -} +private string magicLiteralValue(Literal l) { relevantLiteral(l, result) } private predicate canUseFieldInsteadOfLiteral(Field constField, Literal magicLiteral, string value) { exists(Literal initLiteral | literalIsConstantInitializer(initLiteral, value, constField) and value = initLiteral.getValue() and - value = magicLiteralValue(magicLiteral) - and exists(Declaration d | + value = magicLiteralValue(magicLiteral) and + exists(Declaration d | relevantDeclaration(d, magicLiteral, value) and isVisible(constField, value, d) - ) + ) ) } -predicate literalInsteadOfConstant(Literal magicLiteral, string value, string message, Field constField) { +predicate literalInsteadOfConstant( + Literal magicLiteral, string value, string message, Field constField +) { canUseFieldInsteadOfLiteral(constField, magicLiteral, value) and - message = - "Literal value '" + value + "' used instead of constant $@." + message = "Literal value '" + value + "' used instead of constant $@." } diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql b/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql index 173a8220430..c1a3e5612b6 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql @@ -43,19 +43,16 @@ predicate confusing(Method m1, Method m2) { ) } -/* - * Two method names are confusing if all of the following conditions hold: - * They are both static methods or both instance methods. - * They are not declared in the same class, and the superclass method is - * not overridden in an intermediate class - * They have different names. - * They have the same names if case is ignored. - * There is no method in the subclass that has the same name as - * the superclass method - * There is an additional check that only methods with names longer than one character - * can be considered confusing. - */ - +// Two method names are confusing if all of the following conditions hold: +// They are both static methods or both instance methods. +// They are not declared in the same class, and the superclass method is +// not overridden in an intermediate class +// They have different names. +// They have the same names if case is ignored. +// There is no method in the subclass that has the same name as +// the superclass method +// There is an additional check that only methods with names longer than one character +// can be considered confusing. from Method m1, Method m2 where confusing(m1, m2) and diff --git a/csharp/ql/src/Concurrency/Concurrency.qll b/csharp/ql/src/Concurrency/Concurrency.qll index 232145a2cac..b44ed10886c 100644 --- a/csharp/ql/src/Concurrency/Concurrency.qll +++ b/csharp/ql/src/Concurrency/Concurrency.qll @@ -1,120 +1,78 @@ // Various utilities for writing concurrency queries. - import csharp -class WaitCall extends MethodCall -{ - WaitCall() - { +class WaitCall extends MethodCall { + WaitCall() { getTarget().hasName("Wait") and getTarget().getDeclaringType().hasQualifiedName("System.Threading.Monitor") } - Expr getExpr() - { - result = getArgument(0) - } + Expr getExpr() { result = getArgument(0) } } -class WaitStmt extends ExprStmt -{ - WaitStmt() - { - getExpr() instanceof WaitCall - } +class WaitStmt extends ExprStmt { + WaitStmt() { getExpr() instanceof WaitCall } - Expr getLock() - { - result = ((WaitCall)getExpr()).getExpr() - } + Expr getLock() { result = getExpr().(WaitCall).getExpr() } // If we are waiting on a variable - Variable getWaitVariable() - { - result.getAnAccess() = getLock() - } + Variable getWaitVariable() { result.getAnAccess() = getLock() } // If we are waiting on 'this' - predicate isWaitThis() - { - getLock() instanceof ThisAccess - } + predicate isWaitThis() { getLock() instanceof ThisAccess } // If we are waiting on a typeof() - Type getWaitTypeObject() - { - result = ((TypeofExpr)getLock()).getTypeAccess().getTarget() - } + Type getWaitTypeObject() { result = getLock().(TypeofExpr).getTypeAccess().getTarget() } } -class SynchronizedMethodAttribute extends Attribute -{ - SynchronizedMethodAttribute() - { +class SynchronizedMethodAttribute extends Attribute { + SynchronizedMethodAttribute() { getType().hasQualifiedName("System.Runtime.CompilerServices.MethodImplAttribute") and - exists( MemberConstantAccess a, MemberConstant mc | - a=getArgument(0) and - a.getTarget()=mc and + exists(MemberConstantAccess a, MemberConstant mc | + a = getArgument(0) and + a.getTarget() = mc and mc.hasName("Synchronized") and mc.getDeclaringType().hasQualifiedName("System.Runtime.CompilerServices.MethodImplOptions") - ) + ) } } // A method with attribute [MethodImpl(MethodImplOptions.Synchronized)] -class SynchronizedMethod extends Method -{ - SynchronizedMethod() - { - getAnAttribute() instanceof SynchronizedMethodAttribute - } +class SynchronizedMethod extends Method { + SynchronizedMethod() { getAnAttribute() instanceof SynchronizedMethodAttribute } - predicate isLockThis() - { - not isStatic() - } + predicate isLockThis() { not isStatic() } - Type getLockTypeObject() - { - isStatic() and result=getDeclaringType() - } + Type getLockTypeObject() { isStatic() and result = getDeclaringType() } } -abstract class LockedBlock extends BlockStmt -{ +abstract class LockedBlock extends BlockStmt { abstract predicate isLockThis(); + abstract Variable getLockVariable(); + abstract Type getLockTypeObject(); - Stmt getALockedStmt() - { + Stmt getALockedStmt() { // Do this instead of getParent+, because we don't want to escape // delegates and lambdas result.getParent() = this - or exists( Stmt mid | mid=getALockedStmt() and result.getParent()=mid ) + or + exists(Stmt mid | mid = getALockedStmt() and result.getParent() = mid) } } -class LockStmtBlock extends LockedBlock -{ - LockStmtBlock() - { - exists( LockStmt s | this=s.getBlock() ) +class LockStmtBlock extends LockedBlock { + LockStmtBlock() { exists(LockStmt s | this = s.getBlock()) } + + override predicate isLockThis() { exists(LockStmt s | this = s.getBlock() and s.isLockThis()) } + + override Variable getLockVariable() { + exists(LockStmt s | this = s.getBlock() and result = s.getLockVariable()) } - override predicate isLockThis() - { - exists( LockStmt s | this=s.getBlock() and s.isLockThis() ) - } - - override Variable getLockVariable() - { - exists( LockStmt s | this=s.getBlock() and result=s.getLockVariable() ) - } - - override Type getLockTypeObject() - { - exists( LockStmt s | this=s.getBlock() and result=s.getLockTypeObject() ) + override Type getLockTypeObject() { + exists(LockStmt s | this = s.getBlock() and result = s.getLockTypeObject()) } } @@ -124,32 +82,24 @@ class LockStmtBlock extends LockedBlock class LockingCall extends MethodCall { LockingCall() { this.getTarget() = any(Method m | - m.getDeclaringType().hasQualifiedName("System.Threading", "Monitor") and - m.getName().matches("%Enter%") - ) or + m.getDeclaringType().hasQualifiedName("System.Threading", "Monitor") and + m.getName().matches("%Enter%") + ) or this.getTarget().hasName("EnterReadLock") or this.getTarget().hasName("EnterWriteLock") } } -class SynchronizedMethodBlock extends LockedBlock -{ - SynchronizedMethodBlock() - { - exists( SynchronizedMethod m | this=m.getStatementBody() ) - } - override predicate isLockThis() - { - exists( SynchronizedMethod m | this=m.getStatementBody() and m.isLockThis() ) +class SynchronizedMethodBlock extends LockedBlock { + SynchronizedMethodBlock() { exists(SynchronizedMethod m | this = m.getStatementBody()) } + + override predicate isLockThis() { + exists(SynchronizedMethod m | this = m.getStatementBody() and m.isLockThis()) } - override Variable getLockVariable() - { - none() - } + override Variable getLockVariable() { none() } - override Type getLockTypeObject() - { - exists( SynchronizedMethod m | this=m.getStatementBody() and result=m.getLockTypeObject() ) + override Type getLockTypeObject() { + exists(SynchronizedMethod m | this = m.getStatementBody() and result = m.getLockTypeObject()) } } diff --git a/csharp/ql/src/Concurrency/DataMembers.qll b/csharp/ql/src/Concurrency/DataMembers.qll index 1e70504861e..c012625b9ba 100644 --- a/csharp/ql/src/Concurrency/DataMembers.qll +++ b/csharp/ql/src/Concurrency/DataMembers.qll @@ -4,6 +4,7 @@ * In C#, fields are only one kind of data member -- indexers and properties * give rise to very similar concepts that we may want to treat uniformly. */ + import csharp /** @@ -32,9 +33,7 @@ class DataMember extends Member { * A data member which is also a collection. */ class CollectionMember extends DataMember { - CollectionMember() { - this.getType().(ValueOrRefType).getABaseType*().hasName("ICollection") - } + CollectionMember() { this.getType().(ValueOrRefType).getABaseType*().hasName("ICollection") } /** * Gets an expression corresponding to a read or write of this collection member. @@ -60,8 +59,11 @@ class CollectionMember extends DataMember { // A write of a field or property can be a method call to certain methods... exists(MethodCall call | call = result | call.getQualifier() = this.getAnAccess() and - call.getTarget().getName().regexpMatch("Add.*|Append|Clear.*|Delete|" - + "(Try)?Dequeue|Enqueue|Insert.*|(Try)?Pop|Push|(Try?)Remove.*|Replace.*|SafeDelete|Set.*|") + call + .getTarget() + .getName() + .regexpMatch("Add.*|Append|Clear.*|Delete|" + + "(Try)?Dequeue|Enqueue|Insert.*|(Try)?Pop|Push|(Try?)Remove.*|Replace.*|SafeDelete|Set.*|") ) or // ... or an indexer access that is in an assignment position diff --git a/csharp/ql/src/Concurrency/ThreadCreation.qll b/csharp/ql/src/Concurrency/ThreadCreation.qll index 7f24ea0caa3..5a3b4ba1f65 100644 --- a/csharp/ql/src/Concurrency/ThreadCreation.qll +++ b/csharp/ql/src/Concurrency/ThreadCreation.qll @@ -1,6 +1,7 @@ /** * A library for reasoning about thread creation events in C#. */ + import Concurrency /** @@ -12,7 +13,11 @@ class ThreadStartingCallable extends Callable { this.(Method).getQualifiedName() = "System.Threading.Tasks.Task.Run" or this.(Constructor).getDeclaringType().getQualifiedName() = "System.Threading.Thread" or this.(Method).getQualifiedName() = "System.Threading.Thread.Start" or - this.(Constructor).getDeclaringType().getQualifiedName().matches("System.Threading.Tasks.Task<%>") + this + .(Constructor) + .getDeclaringType() + .getQualifiedName() + .matches("System.Threading.Tasks.Task<%>") } } @@ -26,9 +31,7 @@ abstract class ConcurrentEntryPoint extends Callable { } /** * Methods annotated with the `async` keyword are concurrent entry points. */ -class AsyncMethod extends ConcurrentEntryPoint { - AsyncMethod() { this.(Modifiable).isAsync() } -} +class AsyncMethod extends ConcurrentEntryPoint { AsyncMethod() { this.(Modifiable).isAsync() } } /** * Lambdas or methods passed into the thread or task creation library functions @@ -38,7 +41,8 @@ class LibraryTask extends ConcurrentEntryPoint { LibraryTask() { exists(Call c, Expr arg | c.getTarget() instanceof ThreadStartingCallable and - arg = c.getAnArgument() | + arg = c.getAnArgument() + | this = arg or this = arg.(DelegateCreation).getArgument().(CallableAccess).getTarget() ) diff --git a/csharp/ql/src/Dead Code/DeadCode.qll b/csharp/ql/src/Dead Code/DeadCode.qll index 6d9fa5df7c1..b9e34309258 100644 --- a/csharp/ql/src/Dead Code/DeadCode.qll +++ b/csharp/ql/src/Dead Code/DeadCode.qll @@ -7,7 +7,8 @@ MethodCall getAnAccessByReflection(Method m) { typeof.getTypeAccess().getType() = m.getDeclaringType() and result.getTarget().hasName("GetMethod") and result.getQualifier() = typeof and - result.getArgument(0).getValue() = m.getName()) + result.getArgument(0).getValue() = m.getName() + ) } Expr getAnAccessByDynamicCall(Method m) { @@ -18,15 +19,18 @@ Expr getAnAccessByDynamicCall(Method m) { receiverType instanceof DynamicType or m.getDeclaringType().getABaseType*() = receiverType - ) - and result=call) - or exists(MethodCall mc, Method target | + ) and + result = call + ) + or + exists(MethodCall mc, Method target | target = mc.getTarget() and target.hasName("InvokeMember") and target.getDeclaringType().hasQualifiedName("System.Type") and mc.getArgument(0).(StringLiteral).getValue() = m.getName() and mc.getArgument(3).getType().(RefType).hasMethod(m) and - result=mc) + result = mc + ) } Expr getAMethodAccess(Method m) { @@ -37,14 +41,14 @@ Expr getAMethodAccess(Method m) { } predicate potentiallyAccessedByForEach(Method m) { - m.hasName("GetEnumerator") - and m.getDeclaringType().getABaseType+().hasQualifiedName("System.Collections.IEnumerable") + m.hasName("GetEnumerator") and + m.getDeclaringType().getABaseType+().hasQualifiedName("System.Collections.IEnumerable") } -predicate isRecursivelyLiveExpression(Expr e) -{ - exists(Callable c | c=e.getEnclosingCallable() | - isRecursivelyLiveMethod(c) or not c instanceof Method ) +predicate isRecursivelyLiveExpression(Expr e) { + exists(Callable c | c = e.getEnclosingCallable() | + isRecursivelyLiveMethod(c) or not c instanceof Method + ) } predicate isRecursivelyLiveMethod(Method m) { @@ -69,28 +73,27 @@ predicate isRecursivelyLiveMethod(Method m) { ) } -predicate nunitValueSource(Method m) -{ - exists(ValueSourceAttribute attribute | attribute.getSourceMethod()=m) +predicate nunitValueSource(Method m) { + exists(ValueSourceAttribute attribute | attribute.getSourceMethod() = m) } -predicate nunitTestCaseSource(Declaration f) -{ - exists(TestCaseSourceAttribute attribute | attribute.getSourceDeclaration()=f) +predicate nunitTestCaseSource(Declaration f) { + exists(TestCaseSourceAttribute attribute | attribute.getSourceDeclaration() = f) } predicate isDeadMethod(Method m) { - not isRecursivelyLiveMethod(m) - and m.isSourceDeclaration() + not isRecursivelyLiveMethod(m) and + m.isSourceDeclaration() } predicate isDeadField(Field f) { - f.isPrivate() - and not f.getDeclaringType() instanceof AnonymousClass - and f.getSourceDeclaration() = f - and not nunitTestCaseSource(f) - and forall(FieldAccess fc | fc.getTarget().getSourceDeclaration() = f | + f.isPrivate() and + not f.getDeclaringType() instanceof AnonymousClass and + f.getSourceDeclaration() = f and + not nunitTestCaseSource(f) and + forall(FieldAccess fc | fc.getTarget().getSourceDeclaration() = f | isDeadMethod(fc.getEnclosingCallable()) - or (not fc instanceof FieldRead and not fc.isRefArgument()) + or + not fc instanceof FieldRead and not fc.isRefArgument() ) } diff --git a/csharp/ql/src/Documentation/Documentation.qll b/csharp/ql/src/Documentation/Documentation.qll index 6b9c9d6370a..63c69074f78 100644 --- a/csharp/ql/src/Documentation/Documentation.qll +++ b/csharp/ql/src/Documentation/Documentation.qll @@ -1,10 +1,6 @@ import csharp -class SourceDeclaration extends Declaration { - SourceDeclaration() { - this.isSourceDeclaration() - } -} +class SourceDeclaration extends Declaration { SourceDeclaration() { this.isSourceDeclaration() } } /** A parameter that has come from source code. */ class SourceParameter extends SourceDeclaration, Parameter { } @@ -26,98 +22,87 @@ class SourceMethodOrConstructor extends SourceDeclaration, Callable { } /** Gets an XML comment bound to this declaration. */ -XmlComment getADeclarationXmlComment(Declaration d) -{ - result=getADeclarationCommentBlock(d).getAChild() +XmlComment getADeclarationXmlComment(Declaration d) { + result = getADeclarationCommentBlock(d).getAChild() } /** Gets a comment block bound to this declaration. */ -CommentBlock getADeclarationCommentBlock(Declaration d) -{ +CommentBlock getADeclarationCommentBlock(Declaration d) { // getAfter() is slightly more relaxed than getElement(), // because sometimes CommentBlocks // get split up or don't have spaces before them so aren't // automatically attributed to the declaration. - result.getAfter()=d + result.getAfter() = d } /** Whether the declaration has a documentation comment. */ -predicate declarationHasXmlComment(Declaration d) -{ - exists(getADeclarationXmlComment(d)) -} +predicate declarationHasXmlComment(Declaration d) { exists(getADeclarationXmlComment(d)) } /** Whether a declaration should have documentation. */ -predicate isDocumentationNeeded(Modifiable decl) -{ - decl.getSourceDeclaration()=decl // Exclude constructed types and methods - and not exists(decl.(Attributable).getAnAttribute()) // An attribute may serve to document - and decl.isPublic() - and +predicate isDocumentationNeeded(Modifiable decl) { + decl.getSourceDeclaration() = decl and // Exclude constructed types and methods + not exists(decl.(Attributable).getAnAttribute()) and // An attribute may serve to document + decl.isPublic() and ( // The documentation of the overridden method (e.g. in an interface) is sufficient. - exists(SourceMethod m | decl=m | not m.overrides() ) - or exists(ValueOrRefType t | decl=t | t.fromSource() ) - or decl instanceof SourceConstructor + exists(SourceMethod m | decl = m | not m.overrides()) + or + exists(ValueOrRefType t | decl = t | t.fromSource()) + or + decl instanceof SourceConstructor ) } /** An XML comment containing a `` tag. */ -class ReturnsXmlComment extends XmlComment -{ - ReturnsXmlComment() { getOpenTag(_)="returns" } +class ReturnsXmlComment extends XmlComment { + ReturnsXmlComment() { getOpenTag(_) = "returns" } - predicate hasBody(int offset) { hasBody("returns",offset) } + predicate hasBody(int offset) { hasBody("returns", offset) } - predicate isOpenTag(int offset) { "returns"=getOpenTag(offset) } + predicate isOpenTag(int offset) { "returns" = getOpenTag(offset) } - predicate isEmptyTag(int offset) { "returns"=getEmptyTag(offset) } + predicate isEmptyTag(int offset) { "returns" = getEmptyTag(offset) } } /** An XML comment containing an `` tag. */ -class ExceptionXmlComment extends XmlComment -{ - ExceptionXmlComment() { getOpenTag(_)="exception" } +class ExceptionXmlComment extends XmlComment { + ExceptionXmlComment() { getOpenTag(_) = "exception" } - string getCref(int offset) { result=getAttribute("exception","cref",offset) } + string getCref(int offset) { result = getAttribute("exception", "cref", offset) } - predicate hasBody(int offset) { hasBody("exception",offset) } + predicate hasBody(int offset) { hasBody("exception", offset) } } /** An XML comment containing a `` tag. */ -class ParamXmlComment extends XmlComment -{ - ParamXmlComment() { getOpenTag(_)="param" } +class ParamXmlComment extends XmlComment { + ParamXmlComment() { getOpenTag(_) = "param" } - string getName(int offset) { getAttribute("param","name",offset)=result } + string getName(int offset) { getAttribute("param", "name", offset) = result } - predicate hasBody(int offset) { hasBody("param",offset) } + predicate hasBody(int offset) { hasBody("param", offset) } } /** An XML comment containing a `` tag. */ -class TypeparamXmlComment extends XmlComment -{ - TypeparamXmlComment() { getOpenTag(_)="typeparam" } +class TypeparamXmlComment extends XmlComment { + TypeparamXmlComment() { getOpenTag(_) = "typeparam" } - string getName(int offset) { getAttribute("typeparam","name",offset)=result } + string getName(int offset) { getAttribute("typeparam", "name", offset) = result } - predicate hasBody(int offset) { hasBody("typeparam",offset) } + predicate hasBody(int offset) { hasBody("typeparam", offset) } } /** An XML comment containing a `` tag. */ -class SummaryXmlComment extends XmlComment -{ - SummaryXmlComment() { getOpenTag(_)="summary" } +class SummaryXmlComment extends XmlComment { + SummaryXmlComment() { getOpenTag(_) = "summary" } - predicate hasBody(int offset) { hasBody("summary",offset) } + predicate hasBody(int offset) { hasBody("summary", offset) } - predicate isOpenTag(int offset) { "summary"=getOpenTag(offset) } + predicate isOpenTag(int offset) { "summary" = getOpenTag(offset) } - predicate isEmptyTag(int offset) { "summary"=getEmptyTag(offset) } + predicate isEmptyTag(int offset) { "summary" = getEmptyTag(offset) } } /** An XML comment containing an `` tag. */ -class InheritDocXmlComment extends XmlComment -{ - InheritDocXmlComment() { getOpenTag(_)="inheritdoc" } +class InheritDocXmlComment extends XmlComment { + InheritDocXmlComment() { getOpenTag(_) = "inheritdoc" } } diff --git a/csharp/ql/src/Linq/Helpers.qll b/csharp/ql/src/Linq/Helpers.qll index fe3cf098fad..09643be429a 100644 --- a/csharp/ql/src/Linq/Helpers.qll +++ b/csharp/ql/src/Linq/Helpers.qll @@ -6,143 +6,115 @@ import csharp //#################### PREDICATES #################### - -Stmt firstStmt(ForeachStmt fes) -{ - if fes.getBody() instanceof BlockStmt then - result = fes.getBody().(BlockStmt).getStmt(0) - else - result = fes.getBody() +Stmt firstStmt(ForeachStmt fes) { + if fes.getBody() instanceof BlockStmt + then result = fes.getBody().(BlockStmt).getStmt(0) + else result = fes.getBody() } -predicate isEnumerableType(ValueOrRefType t) -{ - t.hasQualifiedName("System.Linq.Enumerable") -} +predicate isEnumerableType(ValueOrRefType t) { t.hasQualifiedName("System.Linq.Enumerable") } -predicate isIEnumerableType(ValueOrRefType t) -{ +predicate isIEnumerableType(ValueOrRefType t) { t.getQualifiedName().matches("System.Collections.Generic.IEnumerable%") } -predicate missedAllOpportunity(ForeachStmt fes) -{ +predicate missedAllOpportunity(ForeachStmt fes) { exists(IfStmt is | // The loop contains an if statement with no else case, and nothing else. - is = firstStmt(fes) - and numStmts(fes) = 1 - and not exists(is.getElse()) - + is = firstStmt(fes) and + numStmts(fes) = 1 and + not exists(is.getElse()) and // The if statement accesses the loop variable. - and is.getCondition().getAChildExpr*() = fes.getVariable().getAnAccess() - + is.getCondition().getAChildExpr*() = fes.getVariable().getAnAccess() and // The then case of the if assigns false to something and breaks out of the loop. - and exists(Assignment a, BoolLiteral bl | - a = is.getThen().getAChild*() - and bl = a.getRValue() - and bl.toString() = "false" - ) - and exists(BreakStmt bs | - bs = is.getThen().getAChild*() - ) + exists(Assignment a, BoolLiteral bl | + a = is.getThen().getAChild*() and + bl = a.getRValue() and + bl.toString() = "false" + ) and + exists(BreakStmt bs | bs = is.getThen().getAChild*()) ) } -predicate missedCastOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) -{ - s = firstStmt(fes) - and forex(VariableAccess va | va = fes.getVariable().getAnAccess() | va = s.getAVariableDeclExpr().getAChildExpr*()) - and exists(CastExpr ce | - ce = s.getAVariableDeclExpr().getInitializer() - and ce.getExpr() = fes.getVariable().getAnAccess() +predicate missedCastOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) { + s = firstStmt(fes) and + forex(VariableAccess va | va = fes.getVariable().getAnAccess() | + va = s.getAVariableDeclExpr().getAChildExpr*() + ) and + exists(CastExpr ce | + ce = s.getAVariableDeclExpr().getInitializer() and + ce.getExpr() = fes.getVariable().getAnAccess() ) } -predicate missedOfTypeOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) -{ - s = firstStmt(fes) - and forex(VariableAccess va | va = fes.getVariable().getAnAccess() | va = s.getAVariableDeclExpr().getAChildExpr*()) - and exists(AsExpr ae | - ae = s.getAVariableDeclExpr().getInitializer() - and ae.getExpr() = fes.getVariable().getAnAccess() +predicate missedOfTypeOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) { + s = firstStmt(fes) and + forex(VariableAccess va | va = fes.getVariable().getAnAccess() | + va = s.getAVariableDeclExpr().getAChildExpr*() + ) and + exists(AsExpr ae | + ae = s.getAVariableDeclExpr().getInitializer() and + ae.getExpr() = fes.getVariable().getAnAccess() ) } -predicate missedSelectOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) -{ - s = firstStmt(fes) - and forex(VariableAccess va | va = fes.getVariable().getAnAccess() | va = s.getAVariableDeclExpr().getAChildExpr*()) - and not(s.getAVariableDeclExpr().getInitializer() instanceof Cast) +predicate missedSelectOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) { + s = firstStmt(fes) and + forex(VariableAccess va | va = fes.getVariable().getAnAccess() | + va = s.getAVariableDeclExpr().getAChildExpr*() + ) and + not s.getAVariableDeclExpr().getInitializer() instanceof Cast } -predicate missedWhereOpportunity(ForeachStmt fes, IfStmt is) -{ +predicate missedWhereOpportunity(ForeachStmt fes, IfStmt is) { // The very first thing the foreach loop does is test its iteration variable. - is = firstStmt(fes) - and exists(VariableAccess va | - va.getTarget() = fes.getVariable() - and va = is.getCondition().getAChildExpr*() - ) - + is = firstStmt(fes) and + exists(VariableAccess va | + va.getTarget() = fes.getVariable() and + va = is.getCondition().getAChildExpr*() + ) and // It then either (a) continues, or (b) performs the entire body of the loop within the condition. - and ( is.getThen() instanceof ContinueStmt or - ( - not exists(is.getElse()) - and numStmts(fes) = 1 - ) + not exists(is.getElse()) and + numStmts(fes) = 1 ) } -int numStmts(ForeachStmt fes) -{ - if fes.getBody() instanceof BlockStmt then - result = count(fes.getBody().(BlockStmt).getAStmt()) - else - result = 1 +int numStmts(ForeachStmt fes) { + if fes.getBody() instanceof BlockStmt + then result = count(fes.getBody().(BlockStmt).getAStmt()) + else result = 1 } //#################### CLASSES #################### - /** A LINQ Any(...) call. */ -class AnyCall extends MethodCall -{ - AnyCall() - { +class AnyCall extends MethodCall { + AnyCall() { exists(Method m | - m = getTarget() - and isEnumerableType(m.getDeclaringType()) - and m.hasName("Any") + m = getTarget() and + isEnumerableType(m.getDeclaringType()) and + m.hasName("Any") ) } } /** A variable of type IEnumerable<T>, for some T. */ -class IEnumerableSequence extends Variable -{ - IEnumerableSequence() - { - isIEnumerableType(getType()) - } +class IEnumerableSequence extends Variable { + IEnumerableSequence() { isIEnumerableType(getType()) } } /** A LINQ Select(...) call. */ -class SelectCall extends ExtensionMethodCall -{ - SelectCall() - { +class SelectCall extends ExtensionMethodCall { + SelectCall() { exists(Method m | - m = getTarget() - and isEnumerableType(m.getDeclaringType()) - and m.hasName("Select") + m = getTarget() and + isEnumerableType(m.getDeclaringType()) and + m.hasName("Select") ) } /** Gets the anonymous function expression supplied as the argument to the Select (if possible). */ - AnonymousFunctionExpr getFunctionExpr() - { - result = getArgument(1) - } + AnonymousFunctionExpr getFunctionExpr() { result = getArgument(1) } } diff --git a/csharp/ql/src/Metrics/Files/FSelfContainedness.ql b/csharp/ql/src/Metrics/Files/FSelfContainedness.ql index 6763d4881f2..a057479a85c 100644 --- a/csharp/ql/src/Metrics/Files/FSelfContainedness.ql +++ b/csharp/ql/src/Metrics/Files/FSelfContainedness.ql @@ -13,7 +13,7 @@ import csharp import semmle.code.csharp.metrics.Coupling -/* Self-containedness on file level */ +// Self-containedness on file level from File f, float selfContaindness, int efferentSourceCoupling, int efferentCoupling where efferentSourceCoupling = count(File g | diff --git a/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql b/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql index 816503785f0..134031adf43 100644 --- a/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql +++ b/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql @@ -26,10 +26,7 @@ class AntiForgeryAuthorizationFilter extends AuthorizationFilter { * Holds if the project has a global anti forgery filter. */ predicate hasGlobalAntiForgeryFilter() { - /* - * A global filter added - */ - + // A global filter added exists(MethodCall addGlobalFilter | // addGlobalFilter adds a filter to the global filter collection addGlobalFilter.getTarget() = any(GlobalFilterCollection gfc).getAddMethod() and diff --git a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql index 010ba26a406..5a4774a4dc3 100644 --- a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql +++ b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql @@ -19,19 +19,16 @@ import semmle.code.csharp.frameworks.system.Web * Holds if there exists a `Web.config` file in the snapshot that adds an `X-Frame-Options` header. */ predicate hasWebConfigXFrameOptions() { - /* - * Looking for an entry in a Web.config file that looks like this: - * ``` - * - * - * - * - * - * - * - * ``` - */ - + // Looking for an entry in a Web.config file that looks like this: + // ``` + // + // + // + // + // + // + // + // ``` exists(XMLElement element | element = any(WebConfigXML webConfig) .getARootElement() diff --git a/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll b/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll index b7277850fdf..bc187f3017d 100644 --- a/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll +++ b/csharp/ql/src/Security Features/CWE-937/Vulnerabilities.qll @@ -16,26 +16,35 @@ class MicrosoftAdvisory4021279 extends Vulnerability { override string getUrl() { result = "https://github.com/dotnet/corefx/issues/19535" } override predicate matchesRange(string name, Version affected, Version fixed) { - name = "System.Text.Encodings.Web" and ( + name = "System.Text.Encodings.Web" and + ( affected = "4.0.0" and fixed = "4.0.1" or affected = "4.3.0" and fixed = "4.3.1" - ) or - name = "System.Net.Http" and ( + ) + or + name = "System.Net.Http" and + ( affected = "4.1.1" and fixed = "4.1.2" or affected = "4.3.1" and fixed = "4.3.2" - ) or - name = "System.Net.Http.WinHttpHandler" and ( + ) + or + name = "System.Net.Http.WinHttpHandler" and + ( affected = "4.0.1" and fixed = "4.0.2" or affected = "4.3.0" and fixed = "4.3.1" - ) or - name = "System.Net.Security" and ( + ) + or + name = "System.Net.Security" and + ( affected = "4.0.0" and fixed = "4.0.1" or affected = "4.3.0" and fixed = "4.3.1" - ) or ( + ) + or + ( name = "Microsoft.AspNetCore.Mvc" or name = "Microsoft.AspNetCore.Mvc.Core" @@ -63,7 +72,8 @@ class MicrosoftAdvisory4021279 extends Vulnerability { name = "Microsoft.AspNetCore.Mvc.ViewFeatures" or name = "Microsoft.AspNetCore.Mvc.WebApiCompatShim" - ) and ( + ) and + ( affected = "1.0.0" and fixed = "1.0.4" or affected = "1.1.0" and fixed = "1.1.3" @@ -81,7 +91,8 @@ class CVE_2017_8700 extends Vulnerability { name = "Microsoft.AspNetCore.Mvc.Core" or name = "Microsoft.AspNetCore.Mvc.Cors" - ) and ( + ) and + ( affected = "1.0.0" and fixed = "1.0.6" or affected = "1.1.0" and fixed = "1.1.6" @@ -132,7 +143,8 @@ class CVE_2018_8409 extends Vulnerability { name = "System.IO.Pipelines" and affected = "4.5.0" and fixed = "4.5.1" or (name = "Microsoft.AspNetCore.All" or name = "Microsoft.AspNetCore.App") and - affected = "2.1.0" and fixed = "2.1.4" + affected = "2.1.0" and + fixed = "2.1.4" } } @@ -142,7 +154,8 @@ class CVE_2018_8171 extends Vulnerability { override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/310" } override predicate matchesRange(string name, Version affected, Version fixed) { - name = "Microsoft.AspNetCore.Identity" and ( + name = "Microsoft.AspNetCore.Identity" and + ( affected = "1.0.0" and fixed = "1.0.6" or affected = "1.1.0" and fixed = "1.1.6" @@ -166,7 +179,8 @@ class CVE_2018_8356 extends Vulnerability { name = "System.ServiceModel.Http" or name = "System.ServiceModel.NetTcp" - ) and ( + ) and + ( affected = "4.0.0" and fixed = "4.1.3" or affected = "4.3.0" and fixed = "4.3.3" @@ -180,7 +194,8 @@ class CVE_2018_8356 extends Vulnerability { name = "System.ServiceModel.Duplex" or name = "System.ServiceModel.Security" - ) and ( + ) and + ( affected = "4.0.0" and fixed = "4.0.4" or affected = "4.3.0" and fixed = "4.3.3" @@ -190,7 +205,8 @@ class CVE_2018_8356 extends Vulnerability { affected = "4.5.0" and fixed = "4.5.3" ) or - name = "System.ServiceModel.NetTcp" and ( + name = "System.ServiceModel.NetTcp" and + ( affected = "4.0.0" and fixed = "4.1.3" or affected = "4.3.0" and fixed = "4.3.3" @@ -208,13 +224,15 @@ class ASPNETCore_Jul18 extends Vulnerability { override string getUrl() { result = "https://github.com/aspnet/Announcements/issues/311" } override predicate matchesRange(string name, Version affected, Version fixed) { - name = "Microsoft.AspNetCore.Server.Kestrel.Core" and ( + name = "Microsoft.AspNetCore.Server.Kestrel.Core" and + ( affected = "2.0.0" and fixed = "2.0.4" or affected = "2.1.0" and fixed = "2.1.2" ) or - name = "Microsoft.AspNetCore.All" and ( + name = "Microsoft.AspNetCore.All" and + ( affected = "2.0.0" and fixed = "2.0.9" or affected = "2.1.0" and fixed = "2.1.2" @@ -232,7 +250,8 @@ class CVE_2018_8292 extends Vulnerability { override string getUrl() { result = "https://github.com/dotnet/announcements/issues/88" } override predicate matchesVersion(string name, Version affected, Version fixed) { - name = "System.Net.Http" and ( + name = "System.Net.Http" and + ( affected = "2.0" or affected = "4.0.0" or affected = "4.1.0" or @@ -265,12 +284,14 @@ class CVE_2018_0786 extends Vulnerability { name = "System.ServiceModel.Security" or name = "System.Private.ServiceModel" - ) and ( + ) and + ( affected = "4.4.0" and fixed = "4.4.1" or affected = "4.3.0" and fixed = "4.3.1" ) - or ( + or + ( name = "System.ServiceModel.Primitives" or name = "System.ServiceModel.Http" @@ -281,7 +302,8 @@ class CVE_2018_0786 extends Vulnerability { ) and affected = "4.1.0" and fixed = "4.1.1" - or ( + or + ( name = "System.ServiceModel.Duplex" or name = "System.ServiceModel.Security" diff --git a/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll b/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll index 685789ebfac..30ff5a8d9a2 100644 --- a/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll +++ b/csharp/ql/src/Security Features/CWE-937/Vulnerability.qll @@ -6,6 +6,7 @@ import csharp */ class Package extends XMLElement { string name; + Version version; Package() { @@ -19,18 +20,12 @@ class Package extends XMLElement { } /** Gets the name of the package, for example `System.IO.Pipelines`. */ - string getPackageName() { - result = name - } + string getPackageName() { result = name } /** Gets the version of the package, for example `4.5.1`. */ - Version getVersion() { - result = version - } + Version getVersion() { result = version } - override string toString() { - result = name + " " + version - } + override string toString() { result = name + " " + version } } /** @@ -63,8 +58,7 @@ abstract class Vulnerability extends string { */ bindingset[name, version] predicate isVulnerable(string name, Version version, Version fixed) { - exists(Version affected, string n | - name.toLowerCase() = n.toLowerCase() | + exists(Version affected, string n | name.toLowerCase() = n.toLowerCase() | matchesRange(n, affected, fixed) and version.compareTo(fixed) < 0 and version.compareTo(affected) >= 0 @@ -77,7 +71,7 @@ abstract class Vulnerability extends string { bindingset[name, version] private Version getUltimateFix(string name, Version version) { - result = max(Version fix | any(Vulnerability v).isVulnerable(name, version, fix)) + result = max(Version fix | any(Vulnerability v).isVulnerable(name, version, fix)) } /** @@ -86,9 +80,7 @@ private Version getUltimateFix(string name, Version version) { class VulnerablePackage extends Package { Vulnerability vuln; - VulnerablePackage() { - vuln.isVulnerable(this.getPackageName(), this.getVersion(), _) - } + VulnerablePackage() { vuln.isVulnerable(this.getPackageName(), this.getVersion(), _) } /** Gets the vulnerability of this package. */ Vulnerability getVulnerability() { result = vuln } diff --git a/csharp/ql/src/Stubs/MinimalStubsFromSource.ql b/csharp/ql/src/Stubs/MinimalStubsFromSource.ql index 116237d8f17..c4311b40ac2 100644 --- a/csharp/ql/src/Stubs/MinimalStubsFromSource.ql +++ b/csharp/ql/src/Stubs/MinimalStubsFromSource.ql @@ -1,4 +1,4 @@ -/* +/** * Tool to generate C# stubs from a qltest snapshot. * * It finds all declarations used in the source code, diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index 636c8df7694..bcb1a96beb6 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -14,16 +14,13 @@ import csharp /** An element that should be in the generated code. */ -abstract class GeneratedElement extends Element { -} +abstract class GeneratedElement extends Element { } /** A member that should be in the generated code. */ -abstract class GeneratedMember extends Member, GeneratedElement { -} +abstract class GeneratedMember extends Member, GeneratedElement { } /** A type that should be in the generated code. */ -private abstract class GeneratedType extends ValueOrRefType, GeneratedElement { - +abstract private class GeneratedType extends ValueOrRefType, GeneratedElement { GeneratedType() { ( this instanceof Interface @@ -35,12 +32,9 @@ private abstract class GeneratedType extends ValueOrRefType, GeneratedElement { this instanceof Enum or this instanceof DelegateType - ) - and - not this instanceof ConstructedType - and - not this.getALocation() instanceof ExcludedAssembly - and + ) and + not this instanceof ConstructedType and + not this.getALocation() instanceof ExcludedAssembly and this.fromLibrary() } @@ -66,53 +60,37 @@ private abstract class GeneratedType extends ValueOrRefType, GeneratedElement { } private string stubAbstractModifier() { - if this.(Class).isAbstract() then - result = "abstract " - else - result = "" + if this.(Class).isAbstract() then result = "abstract " else result = "" } private string stubStaticModifier() { - if this.isStatic() then result = "static " - else result = "" + if this.isStatic() then result = "static " else result = "" } private string stubAttributes() { - if this.getAnAttribute().getType().getQualifiedName() = "System.FlagsAttribute" then - result = "[System.Flags]\n" - else - result = "" + if this.getAnAttribute().getType().getQualifiedName() = "System.FlagsAttribute" + then result = "[System.Flags]\n" + else result = "" } private string stubComment() { result = "// Generated from `" + this.getQualifiedName() + "` in `" + - min(this.getLocation().toString()) + "`\n" + min(this.getLocation().toString()) + "`\n" } private string stubAccessibilityModifier() { - if this.isPublic() then - result = "public " - else - result = "" + if this.isPublic() then result = "public " else result = "" } /** Gets the entire C# stub code for this type. */ final string getStub() { - if this.isDuplicate() then - result = "" + if this.isDuplicate() + then result = "" else - result = this.stubComment() + - this.stubAttributes() + - this.stubAbstractModifier() + - this.stubStaticModifier() + - this.stubAccessibilityModifier() + - this.stubKeyword() + " " + - this.getUndecoratedName() + - stubGenericArguments(this) + - stubBaseTypesString() + - "\n{\n" + - stubMembers() + - "}\n\n" + result = this.stubComment() + this.stubAttributes() + this.stubAbstractModifier() + + this.stubStaticModifier() + this.stubAccessibilityModifier() + this.stubKeyword() + " " + + this.getUndecoratedName() + stubGenericArguments(this) + stubBaseTypesString() + "\n{\n" + + stubMembers() + "}\n\n" } private ValueOrRefType getAnInterestingBaseType() { @@ -122,25 +100,26 @@ private abstract class GeneratedType extends ValueOrRefType, GeneratedElement { } private string stubBaseTypesString() { - if this instanceof Enum then - result = "" - else if exists(getAnInterestingBaseType()) then - result = " : " + - concat(int i, ValueOrRefType t | - t = this.getAnInterestingBaseType() and (if t instanceof Class then i=0 else i=1) | - stubClassName(t), ", " order by i - ) + if this instanceof Enum + then result = "" else - result = "" + if exists(getAnInterestingBaseType()) + then + result = " : " + + concat(int i, ValueOrRefType t | + t = this.getAnInterestingBaseType() and + (if t instanceof Class then i = 0 else i = 1) + | + stubClassName(t), ", " + order by + i + ) + else result = "" } - private string stubMembers() { - result = concat(stubMember(this.getAGeneratedMember())) - } + private string stubMembers() { result = concat(stubMember(this.getAGeneratedMember())) } - private GeneratedMember getAGeneratedMember() { - result.getDeclaringType() = this - } + private GeneratedMember getAGeneratedMember() { result.getDeclaringType() = this } final Type getAGeneratedType() { result = getAnInterestingBaseType() @@ -160,11 +139,9 @@ private abstract class GeneratedType extends ValueOrRefType, GeneratedElement { * This is extended in client code to identify the actual * declarations that should be generated. */ -abstract class GeneratedDeclaration extends Declaration { -} +abstract class GeneratedDeclaration extends Declaration { } private class IndirectType extends GeneratedType { - IndirectType() { this.getASubType() instanceof GeneratedType or @@ -174,14 +151,14 @@ private class IndirectType extends GeneratedType { or exists(GeneratedType t | this = getAContainedType(t.getAGeneratedType()).getSourceDeclaration()) or - exists(GeneratedDeclaration decl | decl.(Member).getDeclaringType().getSourceDeclaration() = this) + exists(GeneratedDeclaration decl | + decl.(Member).getDeclaringType().getSourceDeclaration() = this + ) } } private class RootGeneratedType extends GeneratedType { - RootGeneratedType() { - this = any(GeneratedDeclaration decl).getSourceDeclaration() - } + RootGeneratedType() { this = any(GeneratedDeclaration decl).getSourceDeclaration() } } private Type getAContainedType(Type t) { @@ -191,9 +168,7 @@ private Type getAContainedType(Type t) { } private class RootGeneratedMember extends GeneratedMember { - RootGeneratedMember() { - this = any(GeneratedDeclaration d).getSourceDeclaration() - } + RootGeneratedMember() { this = any(GeneratedDeclaration d).getSourceDeclaration() } } private predicate declarationExists(Virtualizable m) { @@ -223,31 +198,26 @@ private class GeneratedNamespace extends Namespace, GeneratedElement { } private string getPreamble() { - if this.isGlobalNamespace() then - result = "" - else - result = "namespace " + this.getName() + "\n{\n" + if this.isGlobalNamespace() + then result = "" + else result = "namespace " + this.getName() + "\n{\n" } - private string getPostAmble() { - if this.isGlobalNamespace() then - result = "" - else - result = "}\n" - } + private string getPostAmble() { if this.isGlobalNamespace() then result = "" else result = "}\n" } final string getStubs() { - result = getPreamble() + - getTypeStubs() + - getSubNamespaces() + - getPostAmble() + result = getPreamble() + getTypeStubs() + getSubNamespaces() + getPostAmble() } /** Gets the `n`th generated child namespace, indexed from 0. */ pragma[nomagic] final GeneratedNamespace getChildNamespace(int n) { result.getParentNamespace() = this and - result.getName() = rank[n+1](GeneratedNamespace g | g.getParentNamespace() = this | g.getName()) + result.getName() = rank[n + 1](GeneratedNamespace g | + g.getParentNamespace() = this + | + g.getName() + ) } final int getChildNamespaceCount() { @@ -260,7 +230,9 @@ private class GeneratedNamespace extends Namespace, GeneratedElement { } private string getTypeStubs() { - result = concat(string s | s = any(GeneratedType gt | gt.getDeclaringNamespace() = this).getStub()) + result = concat(string s | + s = any(GeneratedType gt | gt.getDeclaringNamespace() = this).getStub() + ) } } @@ -268,25 +240,32 @@ private class GeneratedNamespace extends Namespace, GeneratedElement { * Specify assemblies to exclude. * Do not generate any types from these assemblies. */ -abstract class ExcludedAssembly extends Assembly { -} +abstract class ExcludedAssembly extends Assembly { } /** Exclude types from these standard assemblies. */ private class DefaultLibs extends ExcludedAssembly { DefaultLibs() { - this.getName() = "System.Private.CoreLib" - or this.getName() = "mscorlib" - or this.getName() = "System.Runtime" + this.getName() = "System.Private.CoreLib" or + this.getName() = "mscorlib" or + this.getName() = "System.Runtime" } } private string stubAccessibility(Member m) { - if m.getDeclaringType() instanceof Interface or exists(m.(Virtualizable).getExplicitlyImplementedInterface()) then result = "" - else if m.isPublic() then result = "public " - else if m.isProtected() then result = "protected " - else if m.isPrivate() then result = "private " - else if m.isInternal() then result = "internal " - else result = "unknown-accessibility" + if + m.getDeclaringType() instanceof Interface or + exists(m.(Virtualizable).getExplicitlyImplementedInterface()) + then result = "" + else + if m.isPublic() + then result = "public " + else + if m.isProtected() + then result = "protected " + else + if m.isPrivate() + then result = "private " + else if m.isInternal() then result = "internal " else result = "unknown-accessibility" } private string stubModifiers(Member m) { @@ -294,71 +273,121 @@ private string stubModifiers(Member m) { } private string stubStatic(Member m) { - if m.(Modifiable).isStatic() then result = "static " - else result = "" + if m.(Modifiable).isStatic() then result = "static " else result = "" } private string stubOverride(Member m) { - if m.getDeclaringType() instanceof Interface then result = "" - else if m.(Virtualizable).isVirtual() then result = "virtual " - else if m.(Virtualizable).isAbstract() then result = "abstract " - else if m.(Virtualizable).isOverride() then result = "override " - else result = "" + if m.getDeclaringType() instanceof Interface + then result = "" + else + if m.(Virtualizable).isVirtual() + then result = "virtual " + else + if m.(Virtualizable).isAbstract() + then result = "abstract " + else if m.(Virtualizable).isOverride() then result = "override " else result = "" } private string stubQualifiedNamePrefix(ValueOrRefType t) { - if t.getParent() instanceof GlobalNamespace then result="" - else if t.getParent() instanceof Namespace then result = t.getParent().(Namespace).getQualifiedName() + "." - else result = stubQualifiedNamePrefix(t.getParent()) + "." + if t.getParent() instanceof GlobalNamespace + then result = "" + else + if t.getParent() instanceof Namespace + then result = t.getParent().(Namespace).getQualifiedName() + "." + else result = stubQualifiedNamePrefix(t.getParent()) + "." } language[monotonicAggregates] private string stubClassName(Type t) { - if t instanceof ObjectType then - result = "object" - else if t instanceof StringType then - result = "string" - else if t instanceof IntType then - result = "int" - else if t instanceof BoolType then - result = "bool" - else if t instanceof VoidType then - result = "void" - else if t instanceof FloatType then - result = "float" - else if t instanceof DoubleType then - result = "double" - else if t instanceof NullableType then - result = stubClassName(t.(NullableType).getUnderlyingType()) + "?" - else if t instanceof TypeParameter then - result = t.getName() - else if t instanceof ArrayType then - result = stubClassName(t.(ArrayType).getElementType()) + "[]" - else if t instanceof PointerType then - result = stubClassName(t.(PointerType).getReferentType()) + "*" - else if t instanceof TupleType then - result = "(" + concat(int i, Type element | element = t.(TupleType).getElementType(i) | stubClassName(element), "," order by i) + ")" - else if t instanceof ValueOrRefType then - result = stubQualifiedNamePrefix(t) + t.getUndecoratedName() + stubGenericArguments(t) + if t instanceof ObjectType + then result = "object" else - result = "" + if t instanceof StringType + then result = "string" + else + if t instanceof IntType + then result = "int" + else + if t instanceof BoolType + then result = "bool" + else + if t instanceof VoidType + then result = "void" + else + if t instanceof FloatType + then result = "float" + else + if t instanceof DoubleType + then result = "double" + else + if t instanceof NullableType + then result = stubClassName(t.(NullableType).getUnderlyingType()) + "?" + else + if t instanceof TypeParameter + then result = t.getName() + else + if t instanceof ArrayType + then result = stubClassName(t.(ArrayType).getElementType()) + "[]" + else + if t instanceof PointerType + then result = stubClassName(t.(PointerType).getReferentType()) + "*" + else + if t instanceof TupleType + then + result = "(" + + concat(int i, Type element | + element = t.(TupleType).getElementType(i) + | + stubClassName(element), "," + order by + i + ) + ")" + else + if t instanceof ValueOrRefType + then + result = stubQualifiedNamePrefix(t) + t.getUndecoratedName() + + stubGenericArguments(t) + else result = "" } language[monotonicAggregates] private string stubGenericArguments(ValueOrRefType t) { - if t instanceof UnboundGenericType then - result = "<" + concat(int n | exists(t.(UnboundGenericType).getTypeParameter(n)) | t.(UnboundGenericType).getTypeParameter(n).getName(),"," order by n) + ">" - else if t instanceof ConstructedType then - result = "<" + concat(int n | exists(t.(ConstructedType).getTypeArgument(n)) | stubClassName(t.(ConstructedType).getTypeArgument(n)),"," order by n) + ">" + if t instanceof UnboundGenericType + then + result = "<" + + concat(int n | + exists(t.(UnboundGenericType).getTypeParameter(n)) + | + t.(UnboundGenericType).getTypeParameter(n).getName(), "," + order by + n + ) + ">" else - result = "" + if t instanceof ConstructedType + then + result = "<" + + concat(int n | + exists(t.(ConstructedType).getTypeArgument(n)) + | + stubClassName(t.(ConstructedType).getTypeArgument(n)), "," + order by + n + ) + ">" + else result = "" } private string stubGenericMethodParams(Method m) { - if m instanceof UnboundGenericMethod then - result = "<" + concat(int n, TypeParameter param | param = m.(UnboundGenericMethod).getTypeParameter(n) | param.getName(), "," order by n) + ">" - else - result = "" + if m instanceof UnboundGenericMethod + then + result = "<" + + concat(int n, TypeParameter param | + param = m.(UnboundGenericMethod).getTypeParameter(n) + | + param.getName(), "," + order by + n + ) + ">" + else result = "" } private string stubImplementation(Virtualizable c) { @@ -368,17 +397,29 @@ private string stubImplementation(Virtualizable c) { } private string stubParameters(Parameterizable p) { - result = concat(int i, Parameter param | param = p.getParameter(i) and not param.getType() instanceof ArglistType | - stubParameterModifiers(param) + stubClassName(param.getType()) + " " + param.getName() + stubDefaultValue(param), ", " order by i) + result = concat(int i, Parameter param | + param = p.getParameter(i) and not param.getType() instanceof ArglistType + | + stubParameterModifiers(param) + stubClassName(param.getType()) + " " + param.getName() + + stubDefaultValue(param), ", " + order by + i + ) } private string stubParameterModifiers(Parameter p) { - if p.isOut() then result = "out " - else if p.isRef() then result = "ref " - else if p.isParams() then result = "params " - else if p.isIn() then result = "" // Only C# 7.1 so ignore - else if p.hasExtensionMethodModifier() then result = "this " - else result = "" + if p.isOut() + then result = "out " + else + if p.isRef() + then result = "ref " + else + if p.isParams() + then result = "params " + else + if p.isIn() + then result = "" // Only C# 7.1 so ignore + else if p.hasExtensionMethodModifier() then result = "this " else result = "" } private string stubDefaultValue(Parameter p) { @@ -395,37 +436,41 @@ private string stubExplicitImplementation(Member c) { private string stubMember(Member m) { exists(Method c | m = c and not m.getDeclaringType() instanceof Enum | - result = " " + stubModifiers(c) + stubClassName(c.getReturnType()) + " " + - stubExplicitImplementation(c) + c.getName() + stubGenericMethodParams(c) + - "(" + stubParameters(c) + ")" + stubImplementation(c) + ";\n" + result = " " + stubModifiers(c) + stubClassName(c.getReturnType()) + " " + + stubExplicitImplementation(c) + c.getName() + stubGenericMethodParams(c) + "(" + + stubParameters(c) + ")" + stubImplementation(c) + ";\n" ) or - exists(Operator op | m = op and not m.getDeclaringType() instanceof Enum and not op instanceof ConversionOperator | + exists(Operator op | + m = op and not m.getDeclaringType() instanceof Enum and not op instanceof ConversionOperator + | result = " " + stubModifiers(op) + stubClassName(op.getReturnType()) + " operator " + - op.getName() +"(" + stubParameters(op) + ") => throw null;\n" + op.getName() + "(" + stubParameters(op) + ") => throw null;\n" ) or exists(ConversionOperator op | m = op | result = " " + stubModifiers(op) + stubExplicit(op) + "operator " + - stubClassName(op.getReturnType()) + "(" + stubParameters(op) + - ") => throw null;\n" + stubClassName(op.getReturnType()) + "(" + stubParameters(op) + ") => throw null;\n" ) or result = " " + m.(EnumConstant).getName() + ",\n" or exists(Property p | m = p | result = " " + stubModifiers(m) + stubClassName(p.getType()) + " " + - stubExplicitImplementation(p) + p.getName() + " { " + stubGetter(p) + stubSetter(p) + "}\n" + stubExplicitImplementation(p) + p.getName() + " { " + stubGetter(p) + stubSetter(p) + "}\n" ) - or exists(Constructor c | m = c and not c.getDeclaringType() instanceof Enum | + or + exists(Constructor c | m = c and not c.getDeclaringType() instanceof Enum | result = " " + stubModifiers(m) + c.getName() + "(" + stubParameters(c) + - ") => throw null;\n" + ") => throw null;\n" ) - or exists(Indexer i | m = i | + or + exists(Indexer i | m = i | result = " " + stubModifiers(m) + stubClassName(i.getType()) + " this[" + stubParameters(i) + - "] { " + stubGetter(i) + stubSetter(i) + "}\n" + "] { " + stubGetter(i) + stubSetter(i) + "}\n" ) - or exists(Field f | f = m and not f instanceof EnumConstant | + or + exists(Field f | f = m and not f instanceof EnumConstant | result = " " + stubModifiers(m) + stubClassName(f.getType()) + " " + f.getName() + ";\n" ) } @@ -437,36 +482,34 @@ private string stubExplicit(ConversionOperator op) { } private string stubGetter(DeclarationWithGetSetAccessors p) { - if exists(p.getGetter()) then ( - if p.isAbstract() or p.getDeclaringType() instanceof Interface then - result = "get; " - else - result = "get => throw null; " - ) else - result = "" + if exists(p.getGetter()) + then + if p.isAbstract() or p.getDeclaringType() instanceof Interface + then result = "get; " + else result = "get => throw null; " + else result = "" } private string stubSetter(DeclarationWithGetSetAccessors p) { - if exists(p.getSetter()) then ( - if p.isAbstract() or p.getDeclaringType() instanceof Interface then - result = "set; " - else - result = "set => throw null; " - ) else - result = "" + if exists(p.getSetter()) + then + if p.isAbstract() or p.getDeclaringType() instanceof Interface + then result = "set; " + else result = "set => throw null; " + else result = "" } private string stubSemmleExtractorOptions() { result = concat(string s | - exists(CommentLine comment | - s = "// original-extractor-options:" + comment.getText().regexpCapture("\\w*semmle-extractor-options:(.*)", 1) + "\n" + exists(CommentLine comment | + s = "// original-extractor-options:" + + comment.getText().regexpCapture("\\w*semmle-extractor-options:(.*)", 1) + "\n" + ) ) - ) } /** Gets the generated C# code. */ string generatedCode() { - result = "// This file contains auto-generated code.\n" + - stubSemmleExtractorOptions() + "\n" + - any(GeneratedNamespace ns | ns.isGlobalNamespace()).getStubs() + result = "// This file contains auto-generated code.\n" + stubSemmleExtractorOptions() + "\n" + + any(GeneratedNamespace ns | ns.isGlobalNamespace()).getStubs() } diff --git a/csharp/ql/src/cil.qll b/csharp/ql/src/cil.qll index 228faa1e4a6..7252542414c 100644 --- a/csharp/ql/src/cil.qll +++ b/csharp/ql/src/cil.qll @@ -1,2 +1 @@ - import semmle.code.cil.CIL as CIL diff --git a/csharp/ql/src/csharp.qll b/csharp/ql/src/csharp.qll index 5a3cc0467ca..45886d6da02 100644 --- a/csharp/ql/src/csharp.qll +++ b/csharp/ql/src/csharp.qll @@ -35,13 +35,10 @@ import semmle.code.csharp.dataflow.TaintTracking import semmle.code.csharp.dataflow.SSA /** DEPRECATED: Use `ControlFlow` instead. */ -deprecated -module ControlFlowGraph { +deprecated module ControlFlowGraph { import semmle.code.csharp.controlflow.ControlFlowGraph import ControlFlow } /** Whether the source was extracted without a build command. */ -predicate extractionIsStandalone() { - exists(SourceFile f | f.extractedStandalone()) -} +predicate extractionIsStandalone() { exists(SourceFile f | f.extractedStandalone()) } diff --git a/csharp/ql/src/external/CodeDuplication.qll b/csharp/ql/src/external/CodeDuplication.qll index 823e425ff64..143fccedbee 100644 --- a/csharp/ql/src/external/CodeDuplication.qll +++ b/csharp/ql/src/external/CodeDuplication.qll @@ -1,9 +1,6 @@ import csharp -private -string relativePath(File file) { - result = file.getRelativePath().replaceAll("\\", "/") -} +private string relativePath(File file) { result = file.getRelativePath().replaceAll("\\", "/") } /** * Holds if the `index`-th token of block `copy` is in file `file`, spanning @@ -17,111 +14,86 @@ predicate tokenLocation(File file, int sl, int sc, int ec, int el, Copy copy, in tokens(copy, index, sl, sc, ec, el) } -class Copy extends @duplication_or_similarity -{ - private - int lastToken() { - result = max(int i | tokens(this, i, _, _, _, _) | i) - } +class Copy extends @duplication_or_similarity { + private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) } int tokenStartingAt(Location loc) { - tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), - _, _, this, result) + tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), _, _, this, result) } int tokenEndingAt(Location loc) { - tokenLocation(loc.getFile(), _, _, - loc.getEndLine(), loc.getEndColumn(), this, result) + tokenLocation(loc.getFile(), _, _, loc.getEndLine(), loc.getEndColumn(), this, result) } - int sourceStartLine() { - tokens(this, 0, result, _, _, _) - } + int sourceStartLine() { tokens(this, 0, result, _, _, _) } - int sourceStartColumn() { - tokens(this, 0, _, result, _, _) - } + int sourceStartColumn() { tokens(this, 0, _, result, _, _) } - int sourceEndLine() { - tokens(this, lastToken(), _, _, result, _) - } + int sourceEndLine() { tokens(this, lastToken(), _, _, result, _) } - int sourceEndColumn() { - tokens(this, lastToken(), _, _, _, result) - } + int sourceEndColumn() { tokens(this, lastToken(), _, _, _, result) } - int sourceLines() { - result = this.sourceEndLine() + 1 - this.sourceStartLine() - } + int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() } - int getEquivalenceClass() { - duplicateCode(this, _, result) or similarCode(this, _, result) - } + int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) } File sourceFile() { - exists(string name | - duplicateCode(this, name, _) or similarCode(this, name, _) | - name.replaceAll("\\", "/") = relativePath(result)) + exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) | + name.replaceAll("\\", "/") = relativePath(result) + ) } - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { - sourceFile().getAbsolutePath() = filepath and - startline = sourceStartLine() and - startcolumn = sourceStartColumn() and - endline = sourceEndLine() and - endcolumn = sourceEndColumn() + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + sourceFile().getAbsolutePath() = filepath and + startline = sourceStartLine() and + startcolumn = sourceStartColumn() and + endline = sourceEndLine() and + endcolumn = sourceEndColumn() } string toString() { none() } } -class DuplicateBlock extends Copy, @duplication -{ - override string toString() { - result = "Duplicate code: " + sourceLines() + " duplicated lines." - } +class DuplicateBlock extends Copy, @duplication { + override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." } } -class SimilarBlock extends Copy, @similarity -{ +class SimilarBlock extends Copy, @similarity { override string toString() { result = "Similar code: " + sourceLines() + " almost duplicated lines." } } - - -Method sourceMethod() { - method_location(result, _) and numlines(result, _, _, _) -} +Method sourceMethod() { method_location(result, _) and numlines(result, _, _, _) } int numberOfSourceMethods(Class c) { result = count(Method m | m = sourceMethod() and m.getDeclaringType() = c) } -private -predicate blockCoversStatement(int equivClass, int first, int last, Stmt stmt) { +private predicate blockCoversStatement(int equivClass, int first, int last, Stmt stmt) { exists(DuplicateBlock b, Location loc | stmt.getLocation() = loc and first = b.tokenStartingAt(loc) and last = b.tokenEndingAt(loc) and - b.getEquivalenceClass() = equivClass) + b.getEquivalenceClass() = equivClass + ) } -private -Stmt statementInMethod(Method m) { +private Stmt statementInMethod(Method m) { result.getEnclosingCallable() = m and not result instanceof BlockStmt } -private -predicate duplicateStatement(Method m1, Method m2, Stmt s1, Stmt s2) { +private predicate duplicateStatement(Method m1, Method m2, Stmt s1, Stmt s2) { exists(int equivClass, int first, int last | s1 = statementInMethod(m1) and s2 = statementInMethod(m2) and blockCoversStatement(equivClass, first, last, s1) and blockCoversStatement(equivClass, first, last, s2) and - s1 != s2 and m1 != m2 + s1 != s2 and + m1 != m2 ) } @@ -138,37 +110,38 @@ predicate duplicateMethod(Method m, Method other) { } predicate similarLines(File f, int line) { - exists(SimilarBlock b | - b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()] - ) + exists(SimilarBlock b | b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()]) } -private -predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) -{ - lines = strictsum(SimilarBlock b, int toSum | (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and (toSum = b.sourceLines()) | toSum) +private predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) { + lines = strictsum(SimilarBlock b, int toSum | + (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and + toSum = b.sourceLines() + | + toSum + ) } -private pragma[noopt] -predicate similarLinesCovered(File f, int coveredLines, File otherFile) { +pragma[noopt] +private predicate similarLinesCovered(File f, int coveredLines, File otherFile) { exists(int numLines | numLines = f.getNumberOfLines() | - exists(int coveredApprox | - coveredApprox = strictsum(int num | - exists(int equivClass | - similarLinesPerEquivalenceClass(equivClass, num, f) and - similarLinesPerEquivalenceClass(equivClass, num, otherFile) and - f != otherFile - ) + exists(int coveredApprox | + coveredApprox = strictsum(int num | + exists(int equivClass | + similarLinesPerEquivalenceClass(equivClass, num, f) and + similarLinesPerEquivalenceClass(equivClass, num, otherFile) and + f != otherFile + ) + ) and + exists(int n, int product | product = coveredApprox * 100 and n = product / numLines | n > 75) ) and - exists (int n, int product| product = coveredApprox * 100 and n = product / numLines | n > 75) - ) and - exists(int notCovered | - notCovered = count(int j | - j in [1 .. numLines] and - not similarLines(f, j) - ) and - coveredLines = numLines - notCovered - ) + exists(int notCovered | + notCovered = count(int j | + j in [1 .. numLines] and + not similarLines(f, j) + ) and + coveredLines = numLines - notCovered + ) ) } @@ -178,32 +151,35 @@ predicate duplicateLines(File f, int line) { ) } -private -predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) -{ - lines = strictsum(DuplicateBlock b, int toSum | (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and (toSum = b.sourceLines()) | toSum) +private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) { + lines = strictsum(DuplicateBlock b, int toSum | + (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and + toSum = b.sourceLines() + | + toSum + ) } -private pragma[noopt] -predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) { +pragma[noopt] +private predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) { exists(int numLines | numLines = f.getNumberOfLines() | - exists(int coveredApprox | - coveredApprox = strictsum(int num | - exists(int equivClass | - duplicateLinesPerEquivalenceClass(equivClass, num, f) and - duplicateLinesPerEquivalenceClass(equivClass, num, otherFile) and - f != otherFile - ) + exists(int coveredApprox | + coveredApprox = strictsum(int num | + exists(int equivClass | + duplicateLinesPerEquivalenceClass(equivClass, num, f) and + duplicateLinesPerEquivalenceClass(equivClass, num, otherFile) and + f != otherFile + ) + ) and + exists(int n, int product | product = coveredApprox * 100 and n = product / numLines | n > 75) ) and - exists (int n, int product| product = coveredApprox * 100 and n = product / numLines | n > 75) - ) and - exists(int notCovered | - notCovered = count(int j | - j in [1 .. numLines] and - not duplicateLines(f, j) - ) and - coveredLines = numLines - notCovered - ) + exists(int notCovered | + notCovered = count(int j | + j in [1 .. numLines] and + not duplicateLines(f, j) + ) and + coveredLines = numLines - notCovered + ) ) } @@ -230,54 +206,59 @@ pragma[noopt] predicate duplicateAnonymousClass(AnonymousClass c, AnonymousClass other) { exists(int numDup | numDup = strictcount(Method m1 | - exists(Method m2 | - duplicateMethod(m1, m2) and - m1 = sourceMethod() and - m1.getDeclaringType() = c and - c instanceof AnonymousClass and - m2.getDeclaringType() = other and - other instanceof AnonymousClass and - c != other - ) - ) and + exists(Method m2 | + duplicateMethod(m1, m2) and + m1 = sourceMethod() and + m1.getDeclaringType() = c and + c instanceof AnonymousClass and + m2.getDeclaringType() = other and + other instanceof AnonymousClass and + c != other + ) + ) and numDup = numberOfSourceMethods(c) and numDup = numberOfSourceMethods(other) and forall(Type t | c.getABaseType() = t | t = other.getABaseType()) ) } -private pragma[noopt] -predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total) { +pragma[noopt] +private predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total) { numDup = strictcount(Method m1 | - exists(Method m2 | - duplicateMethod(m1, m2) and - m1 = sourceMethod() and - m1.getDeclaringType() = c and - m2.getDeclaringType() = other and - other instanceof Class and - c != other - ) - ) and + exists(Method m2 | + duplicateMethod(m1, m2) and + m1 = sourceMethod() and + m1.getDeclaringType() = c and + m2.getDeclaringType() = other and + other instanceof Class and + c != other + ) + ) and total = numberOfSourceMethods(c) and - exists (int n, int product | product = 100 * numDup and n = product / total | n > 80) and + exists(int n, int product | product = 100 * numDup and n = product / total | n > 80) and not c instanceof AnonymousClass and not other instanceof AnonymousClass } predicate mostlyDuplicateClass(Class c, Class other, string message) { exists(int numDup, int total | - mostlyDuplicateClassBase(c,other,numDup,total) and + mostlyDuplicateClassBase(c, other, numDup, total) and ( - (total != numDup - and exists(string s1, string s2, string s3, string name | s1 = " out of " and s2 = " methods in " and s3 = " are duplicated in $@." and name = c.getName() | - message = numDup + s1 + total + s2 + name + s3 - ) + total != numDup and + exists(string s1, string s2, string s3, string name | + s1 = " out of " and + s2 = " methods in " and + s3 = " are duplicated in $@." and + name = c.getName() + | + message = numDup + s1 + total + s2 + name + s3 ) or - (total = numDup - and exists(string s1, string s2, string name | s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName() | - message = s1 + name + s2 - ) + total = numDup and + exists(string s1, string s2, string name | + s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName() + | + message = s1 + name + s2 ) ) ) @@ -291,15 +272,13 @@ predicate classLevelDuplication(Class c, Class other) { duplicateAnonymousClass(c, other) or mostlyDuplicateClass(c, other, _) } -Element whitelistedDuplicateElement() -{ +Element whitelistedDuplicateElement() { result instanceof UsingNamespaceDirective or result instanceof UsingStaticDirective } predicate whitelistedLineForDuplication(File file, int line) { - exists(Location loc | - loc = whitelistedDuplicateElement().getLocation() | + exists(Location loc | loc = whitelistedDuplicateElement().getLocation() | line = loc.getStartLine() and file = loc.getFile() - ) + ) } diff --git a/csharp/ql/src/external/DefectFilter.qll b/csharp/ql/src/external/DefectFilter.qll index 78d460fab10..b1d0cd152fd 100644 --- a/csharp/ql/src/external/DefectFilter.qll +++ b/csharp/ql/src/external/DefectFilter.qll @@ -1,14 +1,20 @@ import csharp -external predicate defectResults(int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, string message); +external predicate defectResults( + int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, + string message +); class DefectResult extends int { - DefectResult() { defectResults(this, _, _, _, _, _, _, _) } string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) } - File getFile() { exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path) } + File getFile() { + exists(string path | + defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path + ) + } int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } @@ -21,7 +27,7 @@ class DefectResult extends int { string getMessage() { defectResults(this, _, _, _, _, _, _, result) } string getURL() { - result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() + result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + + ":" + getEndLine() + ":" + getEndColumn() } - } diff --git a/csharp/ql/src/external/ExternalArtifact.qll b/csharp/ql/src/external/ExternalArtifact.qll index d426a8f31c7..039dd8a7c91 100644 --- a/csharp/ql/src/external/ExternalArtifact.qll +++ b/csharp/ql/src/external/ExternalArtifact.qll @@ -1,15 +1,18 @@ import csharp class ExternalDefect extends @externalDefect, Element { - - string getQueryPath() { exists(string path | externalDefects(this, path, _, _, _) and - result = path.replaceAll("\\", "/")) } + string getQueryPath() { + exists(string path | + externalDefects(this, path, _, _, _) and + result = path.replaceAll("\\", "/") + ) + } string getMessage() { externalDefects(this, _, _, result, _) } float getSeverity() { externalDefects(this, _, _, _, result) } - override Location getLocation() { externalDefects(this,_,result,_,_) } + override Location getLocation() { externalDefects(this, _, result, _, _) } override string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getMessage() @@ -17,20 +20,16 @@ class ExternalDefect extends @externalDefect, Element { } class ExternalMetric extends @externalMetric, Element { - string getQueryPath() { externalMetrics(this, result, _, _) } float getValue() { externalMetrics(this, _, _, result) } - override Location getLocation() { externalMetrics(this,_,result,_) } + override Location getLocation() { externalMetrics(this, _, result, _) } - override string toString() { - result = getQueryPath() + ": " + getLocation() + " - " + getValue() - } + override string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() } } class ExternalData extends @externalDataElement { - string getDataPath() { externalData(this, result, _, _) } string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } @@ -45,16 +44,13 @@ class ExternalData extends @externalDataElement { date getFieldAsDate(int index) { result = getField(index).toDate() } - string toString() { - result = getQueryPath() + ": " + buildTupleString(0) - } + string toString() { result = getQueryPath() + ": " + buildTupleString(0) } private string buildTupleString(int start) { - (start = getNumFields() - 1 and result = getField(start)) + start = getNumFields() - 1 and result = getField(start) or - (start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start+1)) + start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1) } - } /** @@ -70,4 +66,3 @@ class DefectExternalData extends ExternalData { string getMessage() { result = getField(1) } } - diff --git a/csharp/ql/src/external/MetricFilter.qll b/csharp/ql/src/external/MetricFilter.qll index 21dcd4f2813..2ed51092c93 100644 --- a/csharp/ql/src/external/MetricFilter.qll +++ b/csharp/ql/src/external/MetricFilter.qll @@ -1,14 +1,20 @@ import csharp -external predicate metricResults(int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, float value); +external predicate metricResults( + int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, + float value +); class MetricResult extends int { - MetricResult() { metricResults(this, _, _, _, _, _, _, _) } string getQueryPath() { metricResults(this, result, _, _, _, _, _, _) } - File getFile() { exists(string path | metricResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path) } + File getFile() { + exists(string path | + metricResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path + ) + } int getStartLine() { metricResults(this, _, _, result, _, _, _, _) } @@ -31,7 +37,7 @@ class MetricResult extends int { float getValue() { metricResults(this, _, _, _, _, _, _, result) } string getURL() { - result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() + result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + + ":" + getEndLine() + ":" + getEndColumn() } - } diff --git a/csharp/ql/src/external/VCS.qll b/csharp/ql/src/external/VCS.qll index 2182ba2ae7e..99d697cc345 100644 --- a/csharp/ql/src/external/VCS.qll +++ b/csharp/ql/src/external/VCS.qll @@ -1,7 +1,6 @@ import csharp class Commit extends @svnentry { - Commit() { svnaffectedfiles(this, _, _) and exists(date svnDate, date snapshotDate | @@ -31,41 +30,31 @@ class Commit extends @svnentry { string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) } - File getAnAffectedFile(string action) { - svnaffectedfiles(this,result,action) - } + File getAnAffectedFile(string action) { svnaffectedfiles(this, result, action) } File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) } predicate isRecent() { recentCommit(this) } int daysToNow() { - exists(date now | snapshotDate(now) | - result = getDate().daysTo(now) and result >= 0 - ) + exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0) } - int getRecentAdditionsForFile(File f) { - svnchurn(this, f, result, _) - } + int getRecentAdditionsForFile(File f) { svnchurn(this, f, result, _) } - int getRecentDeletionsForFile(File f) { - svnchurn(this, f, _, result) - } + int getRecentDeletionsForFile(File f) { svnchurn(this, f, _, result) } int getRecentChurnForFile(File f) { - exists (int added, int deleted | svnchurn(this,f,added,deleted) and result = added + deleted) + exists(int added, int deleted | svnchurn(this, f, added, deleted) and result = added + deleted) } - } class Author extends string { - Author() { exists(Commit e | this = e.getAuthor()) } + Author() { exists(Commit e | this = e.getAuthor()) } - Commit getACommit() { result.getAuthor() = this } - - File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } + Commit getACommit() { result.getAuthor() = this } + File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } } predicate recentCommit(Commit e) { @@ -73,20 +62,17 @@ predicate recentCommit(Commit e) { snapshotDate(snapshotDate) and e.getDate() = commitDate and days = commitDate.daysTo(snapshotDate) and - days >= 0 and days <= 60 + days >= 0 and + days <= 60 ) } date firstChange(File f) { - result = min(Commit e, date toMin | (f = e.getAnAffectedFile()) and (toMin = e.getDate()) | toMin) + result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin) } predicate firstCommit(Commit e) { - not exists(File f | f = e.getAnAffectedFile() | - firstChange(f) < e.getDate() - ) + not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate()) } -predicate artificialChange(Commit e) { - firstCommit(e) or e.getChangeSize() >= 50000 -} +predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 } diff --git a/csharp/ql/src/semmle/code/asp/AspNet.qll b/csharp/ql/src/semmle/code/asp/AspNet.qll index 16b7abe9ee3..268c7076dac 100644 --- a/csharp/ql/src/semmle/code/asp/AspNet.qll +++ b/csharp/ql/src/semmle/code/asp/AspNet.qll @@ -40,36 +40,22 @@ class AspAttribute extends AspElement, @asp_attribute { } */ class AspOpenTag extends AspElement, @asp_open_tag { /** Either `>` or `/>`, depending on whether it's an empty tag. */ - private string closeAngle() { - if isEmpty() - then result = "/>" - else result = ">" - } + private string closeAngle() { if isEmpty() then result = "/>" else result = ">" } /** Gets the `i`th attribute of this open tag. */ - AspAttribute getAttribute(int i) { - asp_tag_attribute(this, i, _, result) - } + AspAttribute getAttribute(int i) { asp_tag_attribute(this, i, _, result) } /** Gets the attribute named `name`, if any. */ - AspAttribute getAttributeByName(string name) { - asp_tag_attribute(this, _, name, result) - } + AspAttribute getAttributeByName(string name) { asp_tag_attribute(this, _, name, result) } /** Gets the name of this open tag. */ - string getName() { - asp_tag_name(this, result) - } + string getName() { asp_tag_name(this, result) } /** Holds if this open tag has an attribute. */ - predicate hasAttribute() { - asp_tag_attribute(this, _, _, _) - } + predicate hasAttribute() { asp_tag_attribute(this, _, _, _) } /** Holds if this open tag is empty. */ - predicate isEmpty() { - asp_tag_isempty(this) - } + predicate isEmpty() { asp_tag_isempty(this) } override string toString() { if hasAttribute() @@ -89,13 +75,9 @@ class AspOpenTag extends AspElement, @asp_open_tag { */ class AspCloseTag extends AspElement, @asp_close_tag { /** Gets the name of this close tag. */ - string getName() { - result = getBody() - } + string getName() { result = getBody() } - override string toString() { - result = "" - } + override string toString() { result = "" } } /** @@ -111,7 +93,7 @@ class AspCode extends AspAttribute, @asp_code { } class AspBlockCode extends AspCode { AspBlockCode() { not asp_code_inline(this) } - override string toString() { result="<% ... %>" } + override string toString() { result = "<% ... %>" } } /** @@ -120,7 +102,7 @@ class AspBlockCode extends AspCode { class AspInlineCode extends AspCode { AspInlineCode() { asp_code_inline(this) } - override string toString() { result="<%= ... %>" } + override string toString() { result = "<%= ... %>" } } /** A comment, for example ``. */ @@ -146,33 +128,25 @@ class AspServerComment extends AspComment { * ``` */ class AspDataBinding extends AspAttribute, @asp_data_binding { - override string toString() { result="<%# ... %>" } + override string toString() { result = "<%# ... %>" } } /** A directive, for example `<%@ Page Language="C#" %>`. */ class AspDirective extends AspElement, @asp_directive { /** Gets the `i`th attribute of this directive. */ - AspAttribute getAttribute(int i) { - asp_directive_attribute(this, i, _, result) - } + AspAttribute getAttribute(int i) { asp_directive_attribute(this, i, _, result) } /** Gets the attribute named `name`, if any. */ - AspAttribute getAttributeByName(string name) { - asp_directive_attribute(this, _, name, result) - } + AspAttribute getAttributeByName(string name) { asp_directive_attribute(this, _, name, result) } /** * Gets the name of this directive, for example `Page` in * `<%@ Page Language="C#" %>`. */ - string getName() { - asp_directive_name(this, result) - } + string getName() { asp_directive_name(this, result) } /** Holds if this directive has an attribute. */ - predicate hasAttribute() { - exists(getAttribute(_)) - } + predicate hasAttribute() { exists(getAttribute(_)) } override string toString() { if hasAttribute() @@ -191,9 +165,7 @@ class AspQuotedString extends AspAttribute, @asp_quoted_string { } /** Arbitrary text. It will be inserted into the document as is. */ -class AspText extends AspElement, @asp_text { - override string toString() { result=getBody() } -} +class AspText extends AspElement, @asp_text { override string toString() { result = getBody() } } /** An XML directive, such as a `DOCTYPE` declaration. */ class AspXmlDirective extends AspElement, @asp_xml_directive { @@ -209,28 +181,25 @@ class PageDirective extends AspDirective { /** * Gets the 'CodeBehind' class from which this page inherits. */ - ValueOrRefType getInheritedType() { - result.getQualifiedName() = getInheritedTypeQualifiedName() - } + ValueOrRefType getInheritedType() { result.getQualifiedName() = getInheritedTypeQualifiedName() } private string getInheritedTypeQualifiedName() { - /* - * Relevant attributes: - * - `Inherits`: determines the class to inherit from, this is what we want - * - `ClassName`: determines the name to use for the compiled class, can - * provide a fallback namespace if `Inherits` does not have one - * - `CodeBehindFile`/`CodeFile`: used by tooling, but not semantically - * relevant at runtime - */ + // Relevant attributes: + // - `Inherits`: determines the class to inherit from, this is what we want + // - `ClassName`: determines the name to use for the compiled class, can + // provide a fallback namespace if `Inherits` does not have one + // - `CodeBehindFile`/`CodeFile`: used by tooling, but not semantically + // relevant at runtime exists(string inherits | inherits = getAttributeByName("Inherits").getBody() | if inherits.indexOf(".") != -1 then result = inherits - else exists(string className | className = getAttributeByName("ClassName").getBody() | - // take everything up to and including the last . - className.prefix(className.indexOf(".", count(className.indexOf("."))-1, 0)+1) + inherits = result - ) + else + exists(string className | className = getAttributeByName("ClassName").getBody() | + // take everything up to and including the last . + className.prefix(className.indexOf(".", count(className.indexOf(".")) - 1, 0) + 1) + + inherits = result + ) ) - } } @@ -239,22 +208,17 @@ class PageDirective extends AspDirective { */ class CodeBehindFile extends File { CodeBehindFile() { - getExtension() = "aspx" - and + getExtension() = "aspx" and exists(PageDirective pageDir | pageDir.getLocation().getFile() = this) } /** * Gets the `PageDirective` that defines this page. */ - PageDirective getPageDirective() { - result.getLocation().getFile() = this - } + PageDirective getPageDirective() { result.getLocation().getFile() = this } /** * Gets the 'CodeBehind' class from which this page inherits. */ - ValueOrRefType getInheritedType() { - result = getPageDirective().getInheritedType() - } + ValueOrRefType getInheritedType() { result = getPageDirective().getInheritedType() } } diff --git a/csharp/ql/src/semmle/code/asp/WebConfig.qll b/csharp/ql/src/semmle/code/asp/WebConfig.qll index e41070a3c75..8f4fa23cec1 100644 --- a/csharp/ql/src/semmle/code/asp/WebConfig.qll +++ b/csharp/ql/src/semmle/code/asp/WebConfig.qll @@ -1,39 +1,29 @@ /** * Provides classes and predicates related to ASP.NET Web.config files. */ + import csharp /** * A `Web.config` file. */ -class WebConfigXML extends XMLFile { - WebConfigXML() { - getName().matches("%Web.config") - } -} +class WebConfigXML extends XMLFile { WebConfigXML() { getName().matches("%Web.config") } } /** A `` tag in an ASP.NET configuration file. */ class ConfigurationXMLElement extends XMLElement { - - ConfigurationXMLElement() { - this.getName().toLowerCase() = "configuration" - } - + ConfigurationXMLElement() { this.getName().toLowerCase() = "configuration" } } /** A `` tag in an ASP.NET configuration file. */ class LocationXMLElement extends XMLElement { - LocationXMLElement() { this.getParent() instanceof ConfigurationXMLElement and this.getName().toLowerCase() = "location" } - } /** A `` tag in an ASP.NET configuration file. */ class SystemWebXMLElement extends XMLElement { - SystemWebXMLElement() { ( this.getParent() instanceof ConfigurationXMLElement @@ -42,12 +32,10 @@ class SystemWebXMLElement extends XMLElement { ) and this.getName().toLowerCase() = "system.web" } - } /** A `` tag in an ASP.NET configuration file. */ class SystemWebServerXMLElement extends XMLElement { - SystemWebServerXMLElement() { ( this.getParent() instanceof ConfigurationXMLElement @@ -56,26 +44,20 @@ class SystemWebServerXMLElement extends XMLElement { ) and this.getName().toLowerCase() = "system.webserver" } - } /** A `` tag in an ASP.NET configuration file. */ class CustomErrorsXMLElement extends XMLElement { - CustomErrorsXMLElement() { this.getParent() instanceof SystemWebXMLElement and this.getName().toLowerCase() = "customerrors" } - } /** A `` tag in an ASP.NET configuration file. */ class HttpRuntimeXMLElement extends XMLElement { - HttpRuntimeXMLElement() { this.getParent() instanceof SystemWebXMLElement and this.getName().toLowerCase() = "httpruntime" } - } - diff --git a/csharp/ql/src/semmle/code/cil/Access.qll b/csharp/ql/src/semmle/code/cil/Access.qll index 5f956827c96..fca0dd7d9ce 100644 --- a/csharp/ql/src/semmle/code/cil/Access.qll +++ b/csharp/ql/src/semmle/code/cil/Access.qll @@ -8,95 +8,88 @@ private import CIL /** An instruction that accesses a variable. */ class Access extends Instruction, @cil_access { - /** Gets the declaration referenced by this instruction. */ - Variable getTarget() { cil_access(this,result) } - + Variable getTarget() { cil_access(this, result) } } /** * An instruction that accesses a variable. * This class is provided for consistency with the C# data model. */ -class VariableAccess extends Access, @cil_access { -} +class VariableAccess extends Access, @cil_access { } /** An instruction that reads a variable. */ class ReadAccess extends VariableAccess, Expr, @cil_read_access { - override Type getType() { result=getTarget().getType() } + override Type getType() { result = getTarget().getType() } } /** An instruction yielding an address. */ -class ReadRef extends Expr, @cil_read_ref { -} +class ReadRef extends Expr, @cil_read_ref { } /** An instruction that reads the address of a variable. */ -class ReadRefAccess extends ReadAccess, ReadRef { -} +class ReadRefAccess extends ReadAccess, ReadRef { } /** An instruction that writes a variable. */ -class WriteAccess extends VariableAccess, @cil_write_access { - Expr getExpr() { none() } -} +class WriteAccess extends VariableAccess, @cil_write_access { Expr getExpr() { none() } } /** An instruction that accesses a parameter. */ class ParameterAccess extends StackVariableAccess, @cil_arg_access { - override Parameter getTarget() { result=StackVariableAccess.super.getTarget() } + override Parameter getTarget() { result = StackVariableAccess.super.getTarget() } } /** An instruction that reads a parameter. */ class ParameterReadAccess extends ParameterAccess, ReadAccess { - override int getPopCount() { result=0 } + override int getPopCount() { result = 0 } } /** An instruction that writes to a parameter. */ class ParameterWriteAccess extends ParameterAccess, WriteAccess { - override int getPopCount() { result=1 } - override Expr getExpr() { result=getOperand(0) } + override int getPopCount() { result = 1 } + + override Expr getExpr() { result = getOperand(0) } } /** An access to the `this` parameter. */ class ThisAccess extends ParameterReadAccess { - ThisAccess() { - this.getTarget() instanceof ThisParameter - } + ThisAccess() { this.getTarget() instanceof ThisParameter } } /** An instruction that accesses a stack variable. */ class StackVariableAccess extends VariableAccess, @cil_stack_access { - override StackVariable getTarget() { result=VariableAccess.super.getTarget() } + override StackVariable getTarget() { result = VariableAccess.super.getTarget() } } /** An instruction that accesses a local variable. */ class LocalVariableAccess extends StackVariableAccess, @cil_local_access { - override LocalVariable getTarget() { result=StackVariableAccess.super.getTarget() } + override LocalVariable getTarget() { result = StackVariableAccess.super.getTarget() } } /** An instruction that writes to a local variable. */ class LocalVariableWriteAccess extends LocalVariableAccess, WriteAccess { - override int getPopCount() { result=1 } - override Expr getExpr() { result=getOperand(0) } - override string getExtra() { result="L" + getTarget().getIndex() } + override int getPopCount() { result = 1 } + + override Expr getExpr() { result = getOperand(0) } + + override string getExtra() { result = "L" + getTarget().getIndex() } } /** An instruction that reads a local variable. */ class LocalVariableReadAccess extends LocalVariableAccess, ReadAccess { - override int getPopCount() { result=0 } + override int getPopCount() { result = 0 } } /** An instruction that accesses a field. */ class FieldAccess extends VariableAccess, @cil_field_access { - override Field getTarget() { result=VariableAccess.super.getTarget() } - override string getExtra() { result=getTarget().getName() } + override Field getTarget() { result = VariableAccess.super.getTarget() } + + override string getExtra() { result = getTarget().getName() } /** Gets the qualifier of the access, if any. */ abstract Expr getQualifier(); } /** An instruction that reads a field. */ -abstract class FieldReadAccess extends FieldAccess, ReadAccess { -} +abstract class FieldReadAccess extends FieldAccess, ReadAccess { } /** An instruction that writes a field. */ -abstract class FieldWriteAccess extends FieldAccess, WriteAccess { -} +abstract class FieldWriteAccess extends FieldAccess, WriteAccess { } diff --git a/csharp/ql/src/semmle/code/cil/Attribute.qll b/csharp/ql/src/semmle/code/cil/Attribute.qll index 410c2c49d2d..46cb2bf7733 100644 --- a/csharp/ql/src/semmle/code/cil/Attribute.qll +++ b/csharp/ql/src/semmle/code/cil/Attribute.qll @@ -5,12 +5,11 @@ private import semmle.code.csharp.Location as CS /** An attribute to a declaration, such as a method, field, type or parameter. */ class Attribute extends Element, @cil_attribute { - /** Gets the declaration this attribute is attached to. */ - Declaration getDeclaration() { cil_attribute(this,result,_) } + Declaration getDeclaration() { cil_attribute(this, result, _) } /** Gets the constructor used to construct this attribute. */ - Method getConstructor() { cil_attribute(this,_,result) } + Method getConstructor() { cil_attribute(this, _, result) } /** Gets the type of this attribute. */ Type getType() { result = getConstructor().getDeclaringType() } @@ -24,7 +23,7 @@ class Attribute extends Element, @cil_attribute { string getNamedArgument(string name) { cil_attribute_named_argument(this, name, result) } /** Gets an argument of this attribute, if any. */ - string getAnArgument() { result=getArgument(_) or result=getNamedArgument(_) } + string getAnArgument() { result = getArgument(_) or result = getNamedArgument(_) } - override CS::Location getLocation() { result=getDeclaration().getLocation() } + override CS::Location getLocation() { result = getDeclaration().getLocation() } } diff --git a/csharp/ql/src/semmle/code/cil/BasicBlock.qll b/csharp/ql/src/semmle/code/cil/BasicBlock.qll index 8fd2e82c296..9467f12ee74 100644 --- a/csharp/ql/src/semmle/code/cil/BasicBlock.qll +++ b/csharp/ql/src/semmle/code/cil/BasicBlock.qll @@ -10,14 +10,10 @@ private import CIL */ class BasicBlock extends Internal::TBasicBlockStart { /** Gets an immediate successor of this basic block, if any. */ - BasicBlock getASuccessor() { - result.getFirstNode() = getLastNode().getASuccessor() - } + BasicBlock getASuccessor() { result.getFirstNode() = getLastNode().getASuccessor() } /** Gets an immediate predecessor of this basic block, if any. */ - BasicBlock getAPredecessor() { - result.getASuccessor() = this - } + BasicBlock getAPredecessor() { result.getASuccessor() = this } /** * Gets an immediate `true` successor, if any. @@ -35,9 +31,7 @@ class BasicBlock extends Internal::TBasicBlockStart { * The basic block on line 2 is an immediate `true` successor of the * basic block on line 1. */ - BasicBlock getATrueSuccessor() { - result.getFirstNode() = getLastNode().getTrueSuccessor() - } + BasicBlock getATrueSuccessor() { result.getFirstNode() = getLastNode().getTrueSuccessor() } /** * Gets an immediate `false` successor, if any. @@ -55,32 +49,22 @@ class BasicBlock extends Internal::TBasicBlockStart { * The basic block on line 2 is an immediate `false` successor of the * basic block on line 1. */ - BasicBlock getAFalseSuccessor() { - result.getFirstNode() = getLastNode().getFalseSuccessor() - } + BasicBlock getAFalseSuccessor() { result.getFirstNode() = getLastNode().getFalseSuccessor() } /** Gets the control flow node at a specific (zero-indexed) position in this basic block. */ ControlFlowNode getNode(int pos) { Internal::bbIndex(getFirstNode(), result, pos) } /** Gets a control flow node in this basic block. */ - ControlFlowNode getANode() { - result = getNode(_) - } + ControlFlowNode getANode() { result = getNode(_) } /** Gets the first control flow node in this basic block. */ - ControlFlowNode getFirstNode() { - this = Internal::TBasicBlockStart(result) - } + ControlFlowNode getFirstNode() { this = Internal::TBasicBlockStart(result) } /** Gets the last control flow node in this basic block. */ - ControlFlowNode getLastNode() { - result = getNode(length() - 1) - } + ControlFlowNode getLastNode() { result = getNode(length() - 1) } /** Gets the length of this basic block. */ - int length() { - result = strictcount(getANode()) - } + int length() { result = strictcount(getANode()) } /** * Holds if this basic block strictly dominates basic block `bb`. @@ -103,9 +87,7 @@ class BasicBlock extends Internal::TBasicBlockStart { * basic block on line 4 (all paths from the entry point of `M` * to `return s.Length;` must go through the null check). */ - predicate strictlyDominates(BasicBlock bb) { - bbIDominates+(this, bb) - } + predicate strictlyDominates(BasicBlock bb) { bbIDominates+(this, bb) } /** * Holds if this basic block dominates basic block `bb`. @@ -165,10 +147,7 @@ class BasicBlock extends Internal::TBasicBlockStart { /** * Holds if this basic block dominates a predecessor of `df`. */ - private - predicate dominatesPredecessor(BasicBlock df) { - dominates(df.getAPredecessor()) - } + private predicate dominatesPredecessor(BasicBlock df) { dominates(df.getAPredecessor()) } /** * Gets the basic block that immediately dominates this basic block, if any. @@ -192,9 +171,7 @@ class BasicBlock extends Internal::TBasicBlockStart { * to `return s.Length;` must go through the null check, and the null check * is an immediate predecessor of `return s.Length;`). */ - BasicBlock getImmediateDominator() { - bbIDominates(result, this) - } + BasicBlock getImmediateDominator() { bbIDominates(result, this) } /** * Holds if this basic block strictly post-dominates basic block `bb`. @@ -220,9 +197,7 @@ class BasicBlock extends Internal::TBasicBlockStart { * line 3 (all paths to the exit point of `M` from `return s.Length;` * must go through the `WriteLine` call). */ - predicate strictlyPostDominates(BasicBlock bb) { - bbIPostDominates+(this, bb) - } + predicate strictlyPostDominates(BasicBlock bb) { bbIPostDominates+(this, bb) } /** * Holds if this basic block post-dominates basic block `bb`. @@ -261,23 +236,20 @@ class BasicBlock extends Internal::TBasicBlockStart { * even if this basic block is syntactically inside a `while` loop if the * necessary back edges are unreachable. */ - predicate inLoop() { - this.getASuccessor+() = this - } + predicate inLoop() { this.getASuccessor+() = this } /** Gets a textual representation of this basic block. */ - string toString() { - result = getFirstNode().toString() - } + string toString() { result = getFirstNode().toString() } } /** * Internal implementation details. */ -private cached module Internal { +cached +private module Internal { /** Internal representation of basic blocks. */ - cached newtype TBasicBlock = - TBasicBlockStart(ControlFlowNode cfn) { startsBB(cfn) } + cached + newtype TBasicBlock = TBasicBlockStart(ControlFlowNode cfn) { startsBB(cfn) } /** Holds if `cfn` starts a new basic block. */ private predicate startsBB(ControlFlowNode cfn) { @@ -285,7 +257,9 @@ private cached module Internal { or cfn.isJoin() or - exists(ControlFlowNode pred | pred = cfn.getAPredecessor() | strictcount(pred.getASuccessor()) > 1) + exists(ControlFlowNode pred | pred = cfn.getAPredecessor() | + strictcount(pred.getASuccessor()) > 1 + ) } /** @@ -312,18 +286,13 @@ private cached module Internal { * Holds if the first node of basic block `succ` is a control flow * successor of the last node of basic block `pred`. */ -private predicate succBB(BasicBlock pred, BasicBlock succ) { - succ = pred.getASuccessor() -} +private predicate succBB(BasicBlock pred, BasicBlock succ) { succ = pred.getASuccessor() } /** Holds if `dom` is an immediate dominator of `bb`. */ -predicate bbIDominates(BasicBlock dom, BasicBlock bb) = - idominance(entryBB/1, succBB/2)(_, dom, bb) +predicate bbIDominates(BasicBlock dom, BasicBlock bb) = idominance(entryBB/1, succBB/2)(_, dom, bb) /** Holds if `pred` is a basic block predecessor of `succ`. */ -private predicate predBB(BasicBlock succ, BasicBlock pred) { - succBB(pred, succ) -} +private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) } /** Holds if `dom` is an immediate post-dominator of `bb`. */ predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) = @@ -333,34 +302,24 @@ predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) = * An entry basic block, that is, a basic block whose first node is * the entry node of a callable. */ -class EntryBasicBlock extends BasicBlock { - EntryBasicBlock() { entryBB(this) } -} +class EntryBasicBlock extends BasicBlock { EntryBasicBlock() { entryBB(this) } } /** Holds if `bb` is an entry basic block. */ -private predicate entryBB(BasicBlock bb) { - bb.getFirstNode() instanceof EntryPoint -} +private predicate entryBB(BasicBlock bb) { bb.getFirstNode() instanceof EntryPoint } /** * An exit basic block, that is, a basic block whose last node is * an exit node. */ -class ExitBasicBlock extends BasicBlock { - ExitBasicBlock() { exitBB(this) } -} +class ExitBasicBlock extends BasicBlock { ExitBasicBlock() { exitBB(this) } } /** Holds if `bb` is an exit basic block. */ -private predicate exitBB(BasicBlock bb) { - not exists(bb.getLastNode().getASuccessor()) -} +private predicate exitBB(BasicBlock bb) { not exists(bb.getLastNode().getASuccessor()) } /** * A basic block with more than one predecessor. */ -class JoinBlock extends BasicBlock { - JoinBlock() { getFirstNode().isJoin() } -} +class JoinBlock extends BasicBlock { JoinBlock() { getFirstNode().isJoin() } } /** A basic block that terminates in a condition, splitting the subsequent control flow. */ class ConditionBlock extends BasicBlock { @@ -412,9 +371,9 @@ class ConditionBlock extends BasicBlock { * that `this` strictly dominates `controlled` so that isn't necessary to check * directly. */ + exists(BasicBlock succ | - isCandidateSuccessor(succ, testIsTrue) - and + isCandidateSuccessor(succ, testIsTrue) and succ.dominates(controlled) ) } @@ -424,11 +383,7 @@ class ConditionBlock extends BasicBlock { testIsTrue = true and succ = getATrueSuccessor() or testIsTrue = false and succ = getAFalseSuccessor() - ) - and - forall(BasicBlock pred | - pred = succ.getAPredecessor() and pred != this | - succ.dominates(pred) - ) + ) and + forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this | succ.dominates(pred)) } } diff --git a/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll b/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll index 2aea183f530..1ca83005fa8 100644 --- a/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll +++ b/csharp/ql/src/semmle/code/cil/ConsistencyChecks.qll @@ -6,14 +6,10 @@ private import CIL private import csharp as CS private newtype ConsistencyCheck = - MissingEntityCheck() - or - TypeCheck(Type t) - or - CfgCheck(ControlFlowNode n) - or - DeclarationCheck(Declaration d) - or + MissingEntityCheck() or + TypeCheck(Type t) or + CfgCheck(ControlFlowNode n) or + DeclarationCheck(Declaration d) or MissingCSharpCheck(CS::Declaration d) /** @@ -21,6 +17,7 @@ private newtype ConsistencyCheck = */ abstract class ConsistencyViolation extends ConsistencyCheck { abstract string toString(); + abstract string getMessage(); } @@ -29,6 +26,7 @@ abstract class ConsistencyViolation extends ConsistencyCheck { */ abstract class DisabledCheck extends ConsistencyCheck { DisabledCheck() { none() } + abstract string toString(); } @@ -37,40 +35,45 @@ abstract class DisabledCheck extends ConsistencyCheck { */ class CfgViolation extends ConsistencyViolation, CfgCheck { ControlFlowNode getNode() { this = CfgCheck(result) } + override string toString() { result = getNode().toString() } - override abstract string getMessage(); + + abstract override string getMessage(); } /** * A consistency violation in a specific instruction. */ class InstructionViolation extends CfgViolation, CfgCheck { - InstructionViolation() { exists(Instruction i | this=CfgCheck(i)) } + InstructionViolation() { exists(Instruction i | this = CfgCheck(i)) } /** Gets the instruction containing the violation. */ Instruction getInstruction() { this = CfgCheck(result) } private string getInstructionsUpTo() { result = concat(Instruction i | - i.getIndex() <= this.getInstruction().getIndex() and - i.getImplementation() = this.getInstruction().getImplementation() | - i.toString() + " [push: " + i.getPushCount() + ", pop: " + i.getPopCount() + "]", "; " order by i.getIndex() - ) + i.getIndex() <= this.getInstruction().getIndex() and + i.getImplementation() = this.getInstruction().getImplementation() + | + i.toString() + " [push: " + i.getPushCount() + ", pop: " + i.getPopCount() + "]", "; " + order by + i.getIndex() + ) } override string toString() { - result = getInstruction().getImplementation().getMethod().toStringWithTypes() + ": " + getInstruction().toString() + ", " + getInstructionsUpTo() + result = getInstruction().getImplementation().getMethod().toStringWithTypes() + ": " + + getInstruction().toString() + ", " + getInstructionsUpTo() } - override abstract string getMessage(); + + abstract override string getMessage(); } /** * A literal that does not have exactly one `getValue()`. */ class MissingValue extends InstructionViolation { - MissingValue() { - exists(Literal l | l = this.getInstruction() | count(l.getValue()) != 1) - } + MissingValue() { exists(Literal l | l = this.getInstruction() | count(l.getValue()) != 1) } override string getMessage() { result = "Literal has invalid getValue()" } } @@ -79,23 +82,25 @@ class MissingValue extends InstructionViolation { * A call that does not have exactly one `getTarget()`. */ class MissingCallTarget extends InstructionViolation { - MissingCallTarget() { - exists(Call c | c = this.getInstruction() | count(c.getTarget())!=1) - } + MissingCallTarget() { exists(Call c | c = this.getInstruction() | count(c.getTarget()) != 1) } override string getMessage() { result = "Call has invalid target" } } - /** * An instruction that has not been assigned a specific QL class. */ class MissingOpCode extends InstructionViolation { MissingOpCode() { not exists(this.getInstruction().getOpcodeName()) } - override string getMessage() { result = "Opcode " + this.getInstruction().getOpcode() + " is missing a QL class" } - override string toString() { result = "Unknown instruction in " + getInstruction().getImplementation().getMethod().toString() } -} + override string getMessage() { + result = "Opcode " + this.getInstruction().getOpcode() + " is missing a QL class" + } + + override string toString() { + result = "Unknown instruction in " + getInstruction().getImplementation().getMethod().toString() + } +} /** * An instruction that is missing an operand. It means that there is no instruction which pushes @@ -107,15 +112,19 @@ class MissingOpCode extends InstructionViolation { */ class MissingOperand extends InstructionViolation { MissingOperand() { - exists(Instruction i, int op | i=getInstruction() and op in [0..i.getPopCount()-1] | - not exists(i.getOperand(op)) and not i instanceof DeadInstruction) + exists(Instruction i, int op | i = getInstruction() and op in [0 .. i.getPopCount() - 1] | + not exists(i.getOperand(op)) and not i instanceof DeadInstruction + ) } int getMissingOperand() { - result in [0..getInstruction().getPopCount()-1] and not exists(getInstruction().getOperand(result)) + result in [0 .. getInstruction().getPopCount() - 1] and + not exists(getInstruction().getOperand(result)) } - override string getMessage() { result = "This instruction is missing operand " + getMissingOperand() } + override string getMessage() { + result = "This instruction is missing operand " + getMissingOperand() + } } /** @@ -123,11 +132,8 @@ class MissingOperand extends InstructionViolation { * These should not exist, however it turns out that the Mono compiler sometimes * emits them. */ -class DeadInstruction extends Instruction -{ - DeadInstruction() { - not exists(EntryPoint e | e.getASuccessor+() = this) - } +class DeadInstruction extends Instruction { + DeadInstruction() { not exists(EntryPoint e | e.getASuccessor+() = this) } } /** @@ -137,11 +143,10 @@ class DeadInstruction extends Instruction * Disabled, because Mono compiler sometimes emits dead instructions. */ class DeadInstructionViolation extends InstructionViolation, DisabledCheck { - DeadInstructionViolation() { - getInstruction() instanceof DeadInstruction - } + DeadInstructionViolation() { getInstruction() instanceof DeadInstruction } + + override string getMessage() { result = "This instruction is not reachable" } - override string getMessage() { result="This instruction is not reachable" } override string toString() { result = InstructionViolation.super.toString() } } @@ -156,11 +161,12 @@ class InvalidBranchSuccessors extends InstructionViolation { InvalidBranchSuccessors() { // Mono compiler sometimes generates branches to the next instruction, which is just wrong. // However it is valid CIL. - exists(YesNoBranch i | i = getInstruction() | not count(i.getASuccessor()) in [1..2]) + exists(YesNoBranch i | i = getInstruction() | not count(i.getASuccessor()) in [1 .. 2]) } override string getMessage() { - result = "Conditional branch has " + count(this.getInstruction().getASuccessor()) + " successors" + result = "Conditional branch has " + count(this.getInstruction().getASuccessor()) + + " successors" } } @@ -170,7 +176,8 @@ class InvalidBranchSuccessors extends InstructionViolation { class OnlyYesNoBranchHasTrueFalseSuccessors extends InstructionViolation { OnlyYesNoBranchHasTrueFalseSuccessors() { exists(Instruction i | i = getInstruction() | - (exists(i.getTrueSuccessor()) or exists(i.getFalseSuccessor())) and not i instanceof YesNoBranch + (exists(i.getTrueSuccessor()) or exists(i.getFalseSuccessor())) and + not i instanceof YesNoBranch ) } @@ -185,7 +192,9 @@ class UnconditionalBranchSuccessors extends InstructionViolation { exists(UnconditionalBranch i | i = getInstruction() | count(i.getASuccessor()) != 1) } - override string getMessage() { result = "Unconditional branch has " + count(getInstruction().getASuccessor()) + " successors" } + override string getMessage() { + result = "Unconditional branch has " + count(getInstruction().getASuccessor()) + " successors" + } } /** @@ -206,6 +215,7 @@ class NoFalseSuccessor extends InstructionViolation { NoFalseSuccessor() { exists(YesNoBranch i | i = getInstruction() | not exists(i.getFalseSuccessor())) } + override string getMessage() { result = "Missing a false successor" } } @@ -214,7 +224,9 @@ class NoFalseSuccessor extends InstructionViolation { */ class TrueSuccessorIsSuccessor extends InstructionViolation { TrueSuccessorIsSuccessor() { - exists(Instruction i | i = getInstruction() | exists(i.getTrueSuccessor()) and not i.getTrueSuccessor() = i.getASuccessor()) + exists(Instruction i | i = getInstruction() | + exists(i.getTrueSuccessor()) and not i.getTrueSuccessor() = i.getASuccessor() + ) } override string getMessage() { result = "True successor isn't a successor" } @@ -225,7 +237,9 @@ class TrueSuccessorIsSuccessor extends InstructionViolation { */ class FalseSuccessorIsSuccessor extends InstructionViolation { FalseSuccessorIsSuccessor() { - exists(Instruction i | i = getInstruction() | exists(i.getTrueSuccessor()) and not i.getTrueSuccessor() = i.getASuccessor()) + exists(Instruction i | i = getInstruction() | + exists(i.getTrueSuccessor()) and not i.getTrueSuccessor() = i.getASuccessor() + ) } override string getMessage() { result = "True successor isn't a successor" } @@ -235,9 +249,7 @@ class FalseSuccessorIsSuccessor extends InstructionViolation { * An access that does not have exactly one target. */ class AccessMissingTarget extends InstructionViolation { - AccessMissingTarget() { - exists(Access i | i = getInstruction() | count(i.getTarget()) != 1) - } + AccessMissingTarget() { exists(Access i | i = getInstruction() | count(i.getTarget()) != 1) } override string getMessage() { result = "Access has invalid getTarget()" } } @@ -250,7 +262,7 @@ class CatchHandlerMissingType extends CfgViolation { exists(CatchHandler h | h = getNode() | not exists(h.getCaughtType())) } - override string getMessage () { result = "Catch handler missing caught type" } + override string getMessage() { result = "Catch handler missing caught type" } } /** @@ -258,31 +270,33 @@ class CatchHandlerMissingType extends CfgViolation { */ class MissingStackSize extends CfgViolation { MissingStackSize() { - exists(ControlFlowNode node | node=getNode() | - not exists(node.getStackSizeAfter()) - or not exists(node.getStackSizeBefore()) - ) - and not getNode() instanceof DeadInstruction + exists(ControlFlowNode node | node = getNode() | + not exists(node.getStackSizeAfter()) or + not exists(node.getStackSizeBefore()) + ) and + not getNode() instanceof DeadInstruction } override string getMessage() { result = "Inconsistent stack size" } } - /** * A CFG node that does not have exactly one stack size. * Disabled because inconsistent stack sizes have been observed. */ class InvalidStackSize extends CfgViolation, DisabledCheck { InvalidStackSize() { - exists(ControlFlowNode node | node=getNode() | - count(node.getStackSizeAfter()) != 1 - or count(node.getStackSizeBefore()) != 1 - ) - and not getNode() instanceof DeadInstruction + exists(ControlFlowNode node | node = getNode() | + count(node.getStackSizeAfter()) != 1 or + count(node.getStackSizeBefore()) != 1 + ) and + not getNode() instanceof DeadInstruction } - override string getMessage() { result = "Inconsistent stack sizes " + count(getNode().getStackSizeBefore()) + " before and " + count(getNode().getStackSizeAfter()) + " after" } + override string getMessage() { + result = "Inconsistent stack sizes " + count(getNode().getStackSizeBefore()) + " before and " + + count(getNode().getStackSizeAfter()) + " after" + } override string toString() { result = CfgViolation.super.toString() } } @@ -292,10 +306,12 @@ class InvalidStackSize extends CfgViolation, DisabledCheck { */ class InconsistentPopCount extends CfgViolation { InconsistentPopCount() { - exists(ControlFlowNode node | node = getNode() | count(node.getPopCount()) !=1 ) + exists(ControlFlowNode node | node = getNode() | count(node.getPopCount()) != 1) } - override string getMessage() { result = "Cfg node has " + count(getNode().getPopCount()) + " pop counts" } + override string getMessage() { + result = "Cfg node has " + count(getNode().getPopCount()) + " pop counts" + } } /** @@ -306,14 +322,17 @@ class InconsistentPushCount extends CfgViolation { exists(ControlFlowNode node | node = getNode() | count(node.getPushCount()) != 1) } - override string getMessage() { result = "Cfg node has " + count(getNode().getPushCount()) + " push counts" } + override string getMessage() { + result = "Cfg node has " + count(getNode().getPushCount()) + " push counts" + } } /** * A return instruction that does not have a stack size of 0 after it. */ class InvalidReturn extends CfgViolation { - InvalidReturn() { getNode() instanceof Return and getNode().getStackSizeAfter()!=0 } + InvalidReturn() { getNode() instanceof Return and getNode().getStackSizeAfter() != 0 } + override string getMessage() { result = "Return has invalid stack size" } } @@ -321,7 +340,8 @@ class InvalidReturn extends CfgViolation { * A throw instruction that does not have a stack size of 0 after it. */ class InvalidThrow extends CfgViolation { - InvalidThrow() { getNode() instanceof Throw and getNode().getStackSizeAfter()!=0 } + InvalidThrow() { getNode() instanceof Throw and getNode().getStackSizeAfter() != 0 } + override string getMessage() { result = "Throw has invalid stack size" } } @@ -330,9 +350,10 @@ class InvalidThrow extends CfgViolation { */ class StaticFieldTarget extends InstructionViolation { StaticFieldTarget() { - exists(FieldAccess i | i=getInstruction() | - (i instanceof Opcodes::Stfld or i instanceof Opcodes::Stfld) and i.getTarget().isStatic() - ) + exists(FieldAccess i | i = getInstruction() | + (i instanceof Opcodes::Stfld or i instanceof Opcodes::Stfld) and + i.getTarget().isStatic() + ) } override string getMessage() { result = "Inconsistent static field" } @@ -353,12 +374,12 @@ class BranchWithoutTarget extends InstructionViolation { * A consistency violation in a type. */ class TypeViolation extends ConsistencyViolation, TypeCheck { - /** Gets the type containing the violation. */ - Type getType() { this=TypeCheck(result) } + Type getType() { this = TypeCheck(result) } override string toString() { result = getType().toString() } - override abstract string getMessage(); + + abstract override string getMessage(); } /** @@ -377,14 +398,18 @@ class TypeIsBothConstructedAndUnbound extends TypeViolation { */ class TypeParameterMismatch extends TypeViolation { TypeParameterMismatch() { - getType().(ConstructedGeneric).getNumberOfTypeArguments() != getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() + getType().(ConstructedGeneric).getNumberOfTypeArguments() != getType() + .getUnboundType() + .(UnboundGeneric) + .getNumberOfTypeParameters() } override string getMessage() { result = "Constructed type (" + getType().toStringWithTypes() + ") has " + - getType().(ConstructedGeneric).getNumberOfTypeArguments() + " type arguments and unbound type (" + - getType().getUnboundType().toStringWithTypes() + ") has " + - getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() + " type parameters" + getType().(ConstructedGeneric).getNumberOfTypeArguments() + + " type arguments and unbound type (" + getType().getUnboundType().toStringWithTypes() + + ") has " + getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() + + " type parameters" } } @@ -392,11 +417,11 @@ class TypeParameterMismatch extends TypeViolation { * A consistency violation in a method. */ class MethodViolation extends ConsistencyViolation, DeclarationCheck { - /** Gets the method containing the violation. */ Method getMethod() { this = DeclarationCheck(result) } override string toString() { result = getMethod().toString() } + override string getMessage() { none() } } @@ -404,11 +429,16 @@ class MethodViolation extends ConsistencyViolation, DeclarationCheck { * A constructed method that does not match its unbound method. */ class ConstructedMethodTypeParams extends MethodViolation { - - ConstructedMethodTypeParams() { getMethod().(ConstructedGeneric).getNumberOfTypeArguments() != getMethod().getSourceDeclaration().(UnboundGeneric).getNumberOfTypeParameters() } + ConstructedMethodTypeParams() { + getMethod().(ConstructedGeneric).getNumberOfTypeArguments() != getMethod() + .getSourceDeclaration() + .(UnboundGeneric) + .getNumberOfTypeParameters() + } override string getMessage() { - result = "The constructed method " + getMethod().toStringWithTypes() + " does not match unbound method " + getMethod().getSourceDeclaration().toStringWithTypes() + result = "The constructed method " + getMethod().toStringWithTypes() + + " does not match unbound method " + getMethod().getSourceDeclaration().toStringWithTypes() } } @@ -424,6 +454,7 @@ abstract class MissingEntityViolation extends ConsistencyViolation, MissingEntit */ class MissingObjectViolation extends MissingEntityViolation { MissingObjectViolation() { not exists(ObjectType o) } + override string getMessage() { result = "Object missing" } } @@ -433,7 +464,10 @@ class MissingObjectViolation extends MissingEntityViolation { class InvalidOverride extends MethodViolation { InvalidOverride() { exists(Method base | base = getMethod().getOverriddenMethod() | - not getMethod().getDeclaringType().getABaseType+() = getMethod().getOverriddenMethod().getDeclaringType()) + not getMethod().getDeclaringType().getABaseType+() = getMethod() + .getOverriddenMethod() + .getDeclaringType() + ) } override string getMessage() { result = "Overridden method is not in a base type" } @@ -443,9 +477,7 @@ class InvalidOverride extends MethodViolation { * A pointer type that does not have a pointee type. */ class InvalidPointerType extends TypeViolation { - InvalidPointerType() { - exists(PointerType p | p = getType() | count(p.getReferentType()) != 1) - } + InvalidPointerType() { exists(PointerType p | p = getType() | count(p.getReferentType()) != 1) } override string getMessage() { result = "Invalid Pointertype.getPointeeType()" } } @@ -454,9 +486,8 @@ class InvalidPointerType extends TypeViolation { * An array with an invalid `getElementType`. */ class ArrayTypeMissingElement extends TypeViolation { - ArrayTypeMissingElement() { - exists(ArrayType t | t = getType() | count(t.getElementType())!=1) - } + ArrayTypeMissingElement() { exists(ArrayType t | t = getType() | count(t.getElementType()) != 1) } + override string getMessage() { result = "Invalid ArrayType.getElementType()" } } @@ -464,9 +495,8 @@ class ArrayTypeMissingElement extends TypeViolation { * An array with an invalid `getRank`. */ class ArrayTypeInvalidRank extends TypeViolation { - ArrayTypeInvalidRank() { - exists(ArrayType t | t = getType() | not t.getRank() > 0) - } + ArrayTypeInvalidRank() { exists(ArrayType t | t = getType() | not t.getRank() > 0) } + override string getMessage() { result = "Invalid ArrayType.getRank()" } } @@ -474,7 +504,7 @@ class ArrayTypeInvalidRank extends TypeViolation { * A violation in a `Member`. */ abstract class DeclarationViolation extends ConsistencyViolation, DeclarationCheck { - override abstract string getMessage(); + abstract override string getMessage(); /** Gets the member containing the potential violation. */ Declaration getDeclaration() { this = DeclarationCheck(result) } @@ -487,7 +517,7 @@ abstract class DeclarationViolation extends ConsistencyViolation, DeclarationChe */ class PropertyWithNoAccessors extends DeclarationViolation { PropertyWithNoAccessors() { - exists(Property p | p=getDeclaration() | not exists(p.getAnAccessor())) + exists(Property p | p = getDeclaration() | not exists(p.getAnAccessor())) } override string getMessage() { result = "Property has no accessors" } @@ -500,15 +530,14 @@ class ExprPushCount extends InstructionViolation { ExprPushCount() { this.getInstruction() instanceof Expr and not this.getInstruction() instanceof Opcodes::Dup and - if - this.getInstruction() instanceof Call - then - not this.getInstruction().getPushCount() in [0..1] - else - this.getInstruction().(Expr).getPushCount() != 1 + if this.getInstruction() instanceof Call + then not this.getInstruction().getPushCount() in [0 .. 1] + else this.getInstruction().(Expr).getPushCount() != 1 } - override string getMessage() { result = "Instruction has unexpected push count " + this.getInstruction().getPushCount() } + override string getMessage() { + result = "Instruction has unexpected push count " + this.getInstruction().getPushCount() + } } /** @@ -518,12 +547,13 @@ class ExprPushCount extends InstructionViolation { class ExprMissingType extends InstructionViolation { ExprMissingType() { // Don't have types for the following op codes: - not getInstruction() instanceof Opcodes::Ldftn - and not getInstruction() instanceof Opcodes::Localloc - and not getInstruction() instanceof Opcodes::Ldvirtftn - and not getInstruction() instanceof Opcodes::Arglist - and not getInstruction() instanceof Opcodes::Refanytype - and this.getInstruction().getPushCount() = 1 and count(this.getInstruction().getType()) != 1 + not getInstruction() instanceof Opcodes::Ldftn and + not getInstruction() instanceof Opcodes::Localloc and + not getInstruction() instanceof Opcodes::Ldvirtftn and + not getInstruction() instanceof Opcodes::Arglist and + not getInstruction() instanceof Opcodes::Refanytype and + this.getInstruction().getPushCount() = 1 and + count(this.getInstruction().getType()) != 1 } override string getMessage() { result = "Expression is missing getType()" } @@ -533,8 +563,14 @@ class ExprMissingType extends InstructionViolation { * An instruction that has a push count of 0, yet is still used as an operand */ class InvalidExpressionViolation extends InstructionViolation { - InvalidExpressionViolation() { getInstruction().getPushCount()=0 and exists(Instruction expr | getInstruction() = expr.getAnOperand()) } - override string getMessage() { result = "This instruction is used as an operand but pushes no values" } + InvalidExpressionViolation() { + getInstruction().getPushCount() = 0 and + exists(Instruction expr | getInstruction() = expr.getAnOperand()) + } + + override string getMessage() { + result = "This instruction is used as an operand but pushes no values" + } } /** @@ -543,21 +579,22 @@ class InvalidExpressionViolation extends InstructionViolation { */ class TypeMultiplyDefined extends TypeViolation, DisabledCheck { TypeMultiplyDefined() { - this.getType().getParent().getName()="System" - and - not this.getType() instanceof ConstructedGeneric - and - not this.getType() instanceof ArrayType - and - this.getType().isPublic() - and - count(Type t | not t instanceof ConstructedGeneric and t.toStringWithTypes() = this.getType().toStringWithTypes()) != 1 + this.getType().getParent().getName() = "System" and + not this.getType() instanceof ConstructedGeneric and + not this.getType() instanceof ArrayType and + this.getType().isPublic() and + count(Type t | + not t instanceof ConstructedGeneric and + t.toStringWithTypes() = this.getType().toStringWithTypes() + ) != 1 } override string getMessage() { - result="This type (" + getType().toStringWithTypes() + ") has " + - count(Type t | not t instanceof ConstructedGeneric and t.toStringWithTypes() = this.getType().toStringWithTypes()) + - " entities" + result = "This type (" + getType().toStringWithTypes() + ") has " + + count(Type t | + not t instanceof ConstructedGeneric and + t.toStringWithTypes() = this.getType().toStringWithTypes() + ) + " entities" } override string toString() { result = TypeViolation.super.toString() } @@ -567,18 +604,19 @@ class TypeMultiplyDefined extends TypeViolation, DisabledCheck { * A C# declaration which is expected to have a corresponding CIL declaration, but for some reason does not. */ class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck { - - MissingCilDeclaration() - { + MissingCilDeclaration() { exists(CS::Declaration decl | this = MissingCSharpCheck(decl) | - expectedCilDeclaration(decl) - and not exists(Declaration d | decl = d.getCSharpDeclaration()) - ) + expectedCilDeclaration(decl) and + not exists(Declaration d | decl = d.getCSharpDeclaration()) + ) } - CS::Declaration getDeclaration() { this=MissingCSharpCheck(result) } + CS::Declaration getDeclaration() { this = MissingCSharpCheck(result) } - override string getMessage() { result = "Cannot locate CIL for " + getDeclaration().toStringWithTypes() + " of class " + getDeclaration().getAQlClass() } + override string getMessage() { + result = "Cannot locate CIL for " + getDeclaration().toStringWithTypes() + " of class " + + getDeclaration().getAQlClass() + } override string toString() { result = getDeclaration().toStringWithTypes() } } @@ -586,20 +624,20 @@ class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck { /** * Holds if the C# declaration is expected to have a CIl declaration. */ -private predicate expectedCilDeclaration(CS::Declaration decl) -{ - decl=decl.getSourceDeclaration() - and not decl instanceof CS::ArrayType - and decl.getALocation() instanceof CS::Assembly - and not decl.(CS::Modifiable).isInternal() - and not decl.(CS::Constructor).getNumberOfParameters() = 0 // These are sometimes implicit - and not decl.(CS::Method).getReturnType() instanceof CS::UnknownType - and not exists(CS::Parameter p | p = decl.(CS::Parameterizable).getAParameter() | not expectedCilDeclaration(p)) - and not decl instanceof CS::AnonymousClass - and (decl instanceof CS::Parameter implies expectedCilDeclaration(decl.(CS::Parameter).getType())) - and (decl instanceof CS::Parameter implies expectedCilDeclaration(decl.getParent())) - and (decl instanceof CS::Member implies expectedCilDeclaration(decl.getParent())) - and +private predicate expectedCilDeclaration(CS::Declaration decl) { + decl = decl.getSourceDeclaration() and + not decl instanceof CS::ArrayType and + decl.getALocation() instanceof CS::Assembly and + not decl.(CS::Modifiable).isInternal() and + not decl.(CS::Constructor).getNumberOfParameters() = 0 and // These are sometimes implicit + not decl.(CS::Method).getReturnType() instanceof CS::UnknownType and + not exists(CS::Parameter p | p = decl.(CS::Parameterizable).getAParameter() | + not expectedCilDeclaration(p) + ) and + not decl instanceof CS::AnonymousClass and + (decl instanceof CS::Parameter implies expectedCilDeclaration(decl.(CS::Parameter).getType())) and + (decl instanceof CS::Parameter implies expectedCilDeclaration(decl.getParent())) and + (decl instanceof CS::Member implies expectedCilDeclaration(decl.getParent())) and ( decl instanceof CS::Field or @@ -625,10 +663,10 @@ private predicate expectedCilDeclaration(CS::Declaration decl) class MemberWithInvalidName extends DeclarationViolation { MemberWithInvalidName() { exists(string name | name = getDeclaration().(Member).getName() | - exists(name.indexOf(".")) - and not name = ".ctor" - and not name = ".cctor" - ) + exists(name.indexOf(".")) and + not name = ".ctor" and + not name = ".cctor" + ) } override string getMessage() { result = "Invalid name " + getDeclaration().(Member).getName() } @@ -638,31 +676,34 @@ class ConstructedSourceDeclarationMethod extends MethodViolation { Method method; ConstructedSourceDeclarationMethod() { - method = getMethod() - and method = method.getSourceDeclaration() - and (method instanceof ConstructedGeneric or method.getDeclaringType() instanceof ConstructedGeneric) + method = getMethod() and + method = method.getSourceDeclaration() and + ( + method instanceof ConstructedGeneric or + method.getDeclaringType() instanceof ConstructedGeneric + ) } - override string getMessage() { result= "Source declaration " + method.toStringWithTypes() + " is constructed" } + override string getMessage() { + result = "Source declaration " + method.toStringWithTypes() + " is constructed" + } } /** A declaration with multiple labels. */ class DeclarationWithMultipleLabels extends DeclarationViolation { DeclarationWithMultipleLabels() { - exists(Declaration d | - this = DeclarationCheck(d) | - strictcount(d.getLabel()) > 1 - ) + exists(Declaration d | this = DeclarationCheck(d) | strictcount(d.getLabel()) > 1) } - override string getMessage() { result = "Multiple labels " + concat(getDeclaration().getLabel(), ", ") } + override string getMessage() { + result = "Multiple labels " + concat(getDeclaration().getLabel(), ", ") + } } /** A declaration without a label. */ class DeclarationWithoutLabel extends DeclarationViolation { DeclarationWithoutLabel() { - exists(Declaration d | - this = DeclarationCheck(d) | + exists(Declaration d | this = DeclarationCheck(d) | d.isSourceDeclaration() and not d instanceof TypeParameter and not exists(d.getLabel()) and diff --git a/csharp/ql/src/semmle/code/cil/ControlFlow.qll b/csharp/ql/src/semmle/code/cil/ControlFlow.qll index c4434741cbc..f5be4e78cf7 100644 --- a/csharp/ql/src/semmle/code/cil/ControlFlow.qll +++ b/csharp/ql/src/semmle/code/cil/ControlFlow.qll @@ -5,8 +5,7 @@ private import CIL /** A node in the control flow graph. */ -class ControlFlowNode extends @cil_controlflow_node -{ +class ControlFlowNode extends @cil_controlflow_node { /** Gets a textual representation of this control flow node. */ string toString() { none() } @@ -15,22 +14,23 @@ class ControlFlowNode extends @cil_controlflow_node * This value is either 0 or 1, except for the instruction `dup` * which pushes 2 values onto the stack. */ - int getPushCount() { result=0 } + int getPushCount() { result = 0 } /** Gets the number of items this node pops from the stack. */ - int getPopCount() { result=0 } + int getPopCount() { result = 0 } /** Gets a successor of this node, if any. */ - final Instruction getASuccessor() { result=getASuccessorType(_) } + final Instruction getASuccessor() { result = getASuccessorType(_) } /** Gets a true successor of this node, if any. */ - final Instruction getTrueSuccessor() { result=getASuccessorType(any(TrueFlow f)) } + final Instruction getTrueSuccessor() { result = getASuccessorType(any(TrueFlow f)) } /** Gets a false successor of this node, if any. */ - final Instruction getFalseSuccessor() { result=getASuccessorType(any(FalseFlow f)) } + final Instruction getFalseSuccessor() { result = getASuccessorType(any(FalseFlow f)) } /** Gets a successor to this node, of type `type`, if any. */ - cached Instruction getASuccessorType(FlowType t) { none() } + cached + Instruction getASuccessorType(FlowType t) { none() } /** Gets a predecessor of this node, if any. */ ControlFlowNode getAPredecessor() { result.getASuccessor() = this } @@ -47,20 +47,17 @@ class ControlFlowNode extends @cil_controlflow_node i < result.getPushCount() or // Transitive predecessor pushes the operand - exists(ControlFlowNode mid, int pushes | - this.getOperandRec(mid, i, pushes) | + exists(ControlFlowNode mid, int pushes | this.getOperandRec(mid, i, pushes) | pushes - mid.getStackDelta() < result.getPushCount() and result = mid.getAPredecessor() ) } /** Gets an operand of this instruction, if any. */ - ControlFlowNode getAnOperand() { result=getOperand(_) } + ControlFlowNode getAnOperand() { result = getOperand(_) } /** Gets an expression that consumes the output of this instruction on the stack. */ - Instruction getParentExpr() { - this=result.getAnOperand() - } + Instruction getParentExpr() { this = result.getAnOperand() } /** * Holds if `pred` is a transitive predecessor of this instruction, this @@ -70,15 +67,13 @@ class ControlFlowNode extends @cil_controlflow_node */ private predicate getOperandRec(ControlFlowNode pred, int i, int pushes) { // Invariant: no node is a push for operand `i` - pushes >= pred.getPushCount() - and + pushes >= pred.getPushCount() and ( i in [0 .. this.getPopCount() - 1] and pred = this.getAPredecessor() and pushes = i or - exists(ControlFlowNode mid, int pushes0 | - this.getOperandRec(mid, i, pushes0) | + exists(ControlFlowNode mid, int pushes0 | this.getOperandRec(mid, i, pushes0) | pushes = pushes0 - mid.getStackDelta() and // This is a guard to prevent ill formed programs // and other logic errors going into an infinite loop. @@ -88,21 +83,16 @@ class ControlFlowNode extends @cil_controlflow_node ) } - private int getStackDelta() { result = getPushCount()-getPopCount() } + private int getStackDelta() { result = getPushCount() - getPopCount() } /** Gets the stack size before this instruction. */ - int getStackSizeBefore() - { - result = getAPredecessor().getStackSizeAfter() - } + int getStackSizeBefore() { result = getAPredecessor().getStackSizeAfter() } /** Gets the stack size after this instruction. */ - final int getStackSizeAfter() - { + final int getStackSizeAfter() { // This is a guard to prevent ill formed programs // and other logic errors going into an infinite loop. - result in [0..getImplementation().getStackSize()] - and + result in [0 .. getImplementation().getStackSize()] and result = getStackSizeBefore() + getStackDelta() } @@ -110,10 +100,11 @@ class ControlFlowNode extends @cil_controlflow_node MethodImplementation getImplementation() { none() } /** Gets the type of the item pushed onto the stack, if any. */ - cached Type getType() { none() } + cached + Type getType() { none() } /** Holds if this control flow node has more than one predecessor. */ - predicate isJoin() { count(getAPredecessor())>1 } + predicate isJoin() { count(getAPredecessor()) > 1 } } /** @@ -122,27 +113,22 @@ class ControlFlowNode extends @cil_controlflow_node * Handlers are control flow nodes because they push the handled exception onto the stack. */ class EntryPoint extends ControlFlowNode, @cil_entry_point { - override int getStackSizeBefore() { result=0 } + override int getStackSizeBefore() { result = 0 } } -private newtype TFlowType = TNormalFlow() or TTrueFlow() or TFalseFlow() +private newtype TFlowType = + TNormalFlow() or + TTrueFlow() or + TFalseFlow() /** A type of control flow. Either normal flow (`NormalFlow`), true flow (`TrueFlow`) or false flow (`FalseFlow`). */ -abstract class FlowType extends TFlowType { - abstract string toString(); -} +abstract class FlowType extends TFlowType { abstract string toString(); } /** Normal control flow. */ -class NormalFlow extends FlowType, TNormalFlow { - override string toString() { result="" } -} +class NormalFlow extends FlowType, TNormalFlow { override string toString() { result = "" } } /** True control flow. */ -class TrueFlow extends FlowType, TTrueFlow { - override string toString() { result="true" } -} +class TrueFlow extends FlowType, TTrueFlow { override string toString() { result = "true" } } /** False control flow. */ -class FalseFlow extends FlowType, TTrueFlow { - override string toString() { result="false" } -} +class FalseFlow extends FlowType, TTrueFlow { override string toString() { result = "false" } } diff --git a/csharp/ql/src/semmle/code/cil/DataFlow.qll b/csharp/ql/src/semmle/code/cil/DataFlow.qll index c12c6601d04..a9257bcd842 100644 --- a/csharp/ql/src/semmle/code/cil/DataFlow.qll +++ b/csharp/ql/src/semmle/code/cil/DataFlow.qll @@ -21,19 +21,15 @@ class DataFlowNode extends @cil_dataflow_node { * `tt` is the tainting that occurs during this step. */ predicate getALocalFlowSucc(DataFlowNode sink, TaintType tt) { - localExactStep(this, sink) and tt=TExactValue() + localExactStep(this, sink) and tt = TExactValue() or - localTaintStep(this, sink) and tt=TTaintedValue() + localTaintStep(this, sink) and tt = TTaintedValue() } - private predicate flowsToStep(DataFlowNode sink) { - this.getALocalFlowSucc(sink, TExactValue()) - } + private predicate flowsToStep(DataFlowNode sink) { this.getALocalFlowSucc(sink, TExactValue()) } /** Holds if this node flows to `sink` in zero or more steps. */ - predicate flowsTo(DataFlowNode sink) { - this.flowsToStep*(sink) - } + predicate flowsTo(DataFlowNode sink) { this.flowsToStep*(sink) } /** Gets the method that contains this dataflow node. */ Method getMethod() { none() } @@ -49,57 +45,68 @@ private newtype TTaintType = /** Describes how data is tainted. */ class TaintType extends TTaintType { string toString() { - this=TExactValue() and result = "exact" - or this=TTaintedValue() and result = "tainted" + this = TExactValue() and result = "exact" + or + this = TTaintedValue() and result = "tainted" } } /** A taint type where the data is untainted. */ -class Untainted extends TaintType, TExactValue { -} +class Untainted extends TaintType, TExactValue { } /** A taint type where the data is tainted. */ -class Tainted extends TaintType, TTaintedValue { -} +class Tainted extends TaintType, TTaintedValue { } private predicate localExactStep(DataFlowNode src, DataFlowNode sink) { src = sink.(Opcodes::Dup).getAnOperand() - or DefUse::defUse(_, src, sink) - or src=sink.(ParameterReadAccess).getTarget() - or src=sink.(Conversion).getExpr() - or src=sink.(WriteAccess).getExpr() - or src=sink.(Method).getAnImplementation().getAnInstruction().(Return) - or src=sink.(Return).getExpr() - or src=sink.(ConditionalBranch).getAnOperand() - or src=sink.(Parameter).getAWrite() - or exists(VariableUpdate update | update.getVariable().(Parameter)=sink and src=update.getSource()) + or + DefUse::defUse(_, src, sink) + or + src = sink.(ParameterReadAccess).getTarget() + or + src = sink.(Conversion).getExpr() + or + src = sink.(WriteAccess).getExpr() + or + src = sink.(Method).getAnImplementation().getAnInstruction().(Return) + or + src = sink.(Return).getExpr() + or + src = sink.(ConditionalBranch).getAnOperand() + or + src = sink.(Parameter).getAWrite() + or + exists(VariableUpdate update | + update.getVariable().(Parameter) = sink and src = update.getSource() + ) } private predicate localTaintStep(DataFlowNode src, DataFlowNode sink) { - src=sink.(BinaryArithmeticExpr).getAnOperand() - or src=sink.(Opcodes::Neg).getOperand() - or src=sink.(UnaryBitwiseOperation).getOperand() + src = sink.(BinaryArithmeticExpr).getAnOperand() or + src = sink.(Opcodes::Neg).getOperand() or + src = sink.(UnaryBitwiseOperation).getOperand() } -private cached module DefUse { +cached +private module DefUse { /** * A classification of variable references into reads and writes. */ - private newtype RefKind = Read() or Write() + private newtype RefKind = + Read() or + Write() /** * Holds if the `i`th node of basic block `bb` is a reference to `v`, * either a read (when `k` is `Read()`) or a write (when `k` is `Write()`). */ private predicate ref(BasicBlock bb, int i, StackVariable v, RefKind k) { - exists(ReadAccess ra | - bb.getNode(i) = ra | + exists(ReadAccess ra | bb.getNode(i) = ra | ra.getTarget() = v and k = Read() ) or - exists(VariableUpdate vu | - bb.getNode(i) = vu | + exists(VariableUpdate vu | bb.getNode(i) = vu | vu.getVariable() = v and k = Write() ) @@ -156,10 +163,7 @@ private cached module DefUse { private predicate defReachesEndOfBlock(BasicBlock bb, VariableUpdate vu, StackVariable v) { liveAtExit(bb, v) and ( - exists(int last | - last = max(refRank(bb, _, v, _)) | - defReachesRank(bb, vu, last, v) - ) + exists(int last | last = max(refRank(bb, _, v, _)) | defReachesRank(bb, vu, last, v)) or exists(BasicBlock pred | pred = bb.getAPredecessor() and @@ -184,8 +188,7 @@ private cached module DefUse { /** Holds if the update `def` can be used at the read `use`. */ cached predicate defUse(StackVariable target, DataFlowNode def, ReadAccess use) { - exists(VariableUpdate vu | - def = vu.getSource() | + exists(VariableUpdate vu | def = vu.getSource() | defReachesReadWithinBlock(target, vu, use) or exists(BasicBlock bb, int i | @@ -198,26 +201,26 @@ private cached module DefUse { } } -library abstract class VariableUpdate extends Instruction { +abstract library class VariableUpdate extends Instruction { abstract Expr getSource(); + abstract Variable getVariable(); } private class VariableWrite extends VariableUpdate, WriteAccess { - override Expr getSource() { result=getExpr() } - override Variable getVariable() { result=getTarget() } + override Expr getSource() { result = getExpr() } + + override Variable getVariable() { result = getTarget() } } private class MethodOutOrRefTarget extends VariableUpdate, Call { int parameterIndex; - MethodOutOrRefTarget() { - this.getTarget().getRawParameter(parameterIndex).hasOutFlag() - } + MethodOutOrRefTarget() { this.getTarget().getRawParameter(parameterIndex).hasOutFlag() } override Variable getVariable() { - result=this.getRawArgument(parameterIndex).(ReadAccess).getTarget() + result = this.getRawArgument(parameterIndex).(ReadAccess).getTarget() } - override Expr getSource() { result=this } + override Expr getSource() { result = this } } diff --git a/csharp/ql/src/semmle/code/cil/Declaration.qll b/csharp/ql/src/semmle/code/cil/Declaration.qll index 04547cc7a1f..956b72f126e 100644 --- a/csharp/ql/src/semmle/code/cil/Declaration.qll +++ b/csharp/ql/src/semmle/code/cil/Declaration.qll @@ -10,9 +10,8 @@ private import semmle.code.csharp.Member as CS * A declaration. Either a member (`Member`) or a variable (`Variable`). */ class Declaration extends DotNet::Declaration, Element, @cil_declaration { - /** Gets an attribute (for example `[Obsolete]`) of this declaration, if any. */ - Attribute getAnAttribute() { result.getDeclaration()=this } + Attribute getAnAttribute() { result.getDeclaration() = this } /** * Gets the C# declaration corresponding to this CIL declaration, if any. @@ -23,21 +22,19 @@ class Declaration extends DotNet::Declaration, Element, @cil_declaration { result = toCSharpTypeParameter(this) } - override Declaration getSourceDeclaration() { result=this } + override Declaration getSourceDeclaration() { result = this } /** Holds if this declaration is a source declaration. */ - final predicate isSourceDeclaration() { this=getSourceDeclaration() } + final predicate isSourceDeclaration() { this = getSourceDeclaration() } } -private CS::Declaration toCSharpNonTypeParameter(Declaration d) { - result.getLabel() = d.getLabel() -} +private CS::Declaration toCSharpNonTypeParameter(Declaration d) { result.getLabel() = d.getLabel() } private CS::TypeParameter toCSharpTypeParameter(TypeParameter tp) { toCSharpTypeParameterJoin(tp, result.getIndex(), result.getGeneric()) } -pragma [noinline, nomagic] +pragma[noinline, nomagic] private predicate toCSharpTypeParameterJoin(TypeParameter tp, int i, CS::UnboundGeneric ug) { exists(TypeContainer tc | tp.getIndex() = i and @@ -87,17 +84,20 @@ class Property extends DotNet::Property, Member, @cil_property { override ValueOrRefType getDeclaringType() { cil_property(this, result, _, _) } /** Gets the getter of this property, if any. */ - override Getter getGetter() { this=result.getProperty() } + override Getter getGetter() { this = result.getProperty() } /** Gets the setter of this property, if any. */ - override Setter getSetter() { this=result.getProperty() } + override Setter getSetter() { this = result.getProperty() } /** Gets an accessor of this property. */ - Accessor getAnAccessor() { result=getGetter() or result=getSetter() } + Accessor getAnAccessor() { result = getGetter() or result = getSetter() } - override string toString() { result="property " + getName() } + override string toString() { result = "property " + getName() } - override string toStringWithTypes() { result=getType().toStringWithTypes() + " " + getDeclaringType().toStringWithTypes() + "." + getName() } + override string toStringWithTypes() { + result = getType().toStringWithTypes() + " " + getDeclaringType().toStringWithTypes() + "." + + getName() + } } /** A property that is trivial (wraps a field). */ @@ -107,16 +107,16 @@ class TrivialProperty extends Property { } /** Gets the underlying field of this property. */ - Field getField() { result=getGetter().(TrivialGetter).getField() } + Field getField() { result = getGetter().(TrivialGetter).getField() } } /** An event. */ -class Event extends DotNet::Event, Member, @cil_event -{ +class Event extends DotNet::Event, Member, @cil_event { override string getName() { cil_event(this, _, result, _) } /** Gets the type of this event. */ Type getType() { cil_event(this, _, _, result) } + override ValueOrRefType getDeclaringType() { cil_event(this, result, _, _) } /** Gets the add event accessor. */ @@ -128,7 +128,9 @@ class Event extends DotNet::Event, Member, @cil_event /** Gets the raiser. */ Method getRaiser() { cil_raiser(this, result) } - override string toString() { result="event " + getName() } + override string toString() { result = "event " + getName() } - override string toStringWithTypes() { result=getDeclaringType().toStringWithTypes() + "." + getName() } + override string toStringWithTypes() { + result = getDeclaringType().toStringWithTypes() + "." + getName() + } } diff --git a/csharp/ql/src/semmle/code/cil/Generics.qll b/csharp/ql/src/semmle/code/cil/Generics.qll index 6da41240d10..355a977e201 100644 --- a/csharp/ql/src/semmle/code/cil/Generics.qll +++ b/csharp/ql/src/semmle/code/cil/Generics.qll @@ -1,4 +1,5 @@ /** Provides classes for generic types and methods. */ + private import CIL private import dotnet @@ -15,24 +16,16 @@ class Generic extends DotNet::Generic, Declaration, TypeContainer { /** An unbound generic type or method. */ class UnboundGeneric extends Generic, DotNet::UnboundGeneric { - UnboundGeneric() { - cil_type_parameter(this, _, _) - } + UnboundGeneric() { cil_type_parameter(this, _, _) } - final override TypeParameter getTypeParameter(int n) { - cil_type_parameter(this, n, result) - } + final override TypeParameter getTypeParameter(int n) { cil_type_parameter(this, n, result) } } /** A constructed generic type or method. */ class ConstructedGeneric extends Generic, DotNet::ConstructedGeneric { - ConstructedGeneric() { - cil_type_argument(this, _, _) - } + ConstructedGeneric() { cil_type_argument(this, _, _) } - final override Type getTypeArgument(int n) { - cil_type_argument(this, n, result) - } + final override Type getTypeArgument(int n) { cil_type_argument(this, n, result) } } /** An unbound generic type. */ @@ -48,7 +41,5 @@ class ConstructedType extends ConstructedGeneric, Type { } class ConstructedMethod extends ConstructedGeneric, Method { final override UnboundGenericMethod getUnboundGeneric() { result = getUnboundMethod() } - final override Location getLocation() { - result = getUnboundGeneric().getLocation() - } + final override Location getLocation() { result = getUnboundGeneric().getLocation() } } diff --git a/csharp/ql/src/semmle/code/cil/Handler.qll b/csharp/ql/src/semmle/code/cil/Handler.qll index 4649c26bd37..da90fe872db 100644 --- a/csharp/ql/src/semmle/code/cil/Handler.qll +++ b/csharp/ql/src/semmle/code/cil/Handler.qll @@ -19,70 +19,65 @@ private import CIL * Either a finally handler (`FinallyHandler`), filter handler (`FilterHandler`), * catch handler (`CatchHandler`), or a fault handler (`FaultHandler`). */ -class Handler extends Element, EntryPoint, @cil_handler -{ - override MethodImplementation getImplementation() { cil_handler(this,result,_,_,_,_,_) } +class Handler extends Element, EntryPoint, @cil_handler { + override MethodImplementation getImplementation() { cil_handler(this, result, _, _, _, _, _) } /** Gets the 0-based index of this handler. Handlers are evaluated in this sequence. */ int getIndex() { cil_handler(this, _, result, _, _, _, _) } /** Gets the first instruction in the `try` block of this handler. */ - Instruction getTryStart() { cil_handler(this,_,_,_,result,_,_) } + Instruction getTryStart() { cil_handler(this, _, _, _, result, _, _) } /** Gets the last instruction in the `try` block of this handler. */ - Instruction getTryEnd() { cil_handler(this,_,_,_,_,result,_) } + Instruction getTryEnd() { cil_handler(this, _, _, _, _, result, _) } /** Gets the first instruction in the `catch`/`finally` block. */ - Instruction getHandlerStart() { cil_handler(this,_,_,_,_,_,result) } + Instruction getHandlerStart() { cil_handler(this, _, _, _, _, _, result) } /** * Holds if the instruction `i` is in the scope of this handler. */ predicate isInScope(Instruction i) { - i.getImplementation() = getImplementation() - and - i.getIndex() in [getTryStart().getIndex()..getTryEnd().getIndex()] + i.getImplementation() = getImplementation() and + i.getIndex() in [getTryStart().getIndex() .. getTryEnd().getIndex()] } override string toString() { none() } override Instruction getASuccessorType(FlowType t) { - result = getHandlerStart() - and + result = getHandlerStart() and t instanceof NormalFlow } /** Gets the type of the caught exception, if any. */ - Type getCaughtType() { cil_handler_type(this,result) } + Type getCaughtType() { cil_handler_type(this, result) } - override Location getLocation() { result=getTryStart().getLocation() } + override Location getLocation() { result = getTryStart().getLocation() } } /** A handler corresponding to a `finally` block. */ -class FinallyHandler extends Handler, @cil_finally_handler -{ +class FinallyHandler extends Handler, @cil_finally_handler { override string toString() { result = "finally {...}" } } /** A handler corresponding to a `where()` clause. */ -class FilterHandler extends Handler, @cil_filter_handler -{ - override string toString() { result="where (...)" } +class FilterHandler extends Handler, @cil_filter_handler { + override string toString() { result = "where (...)" } /** Gets the filter clause - the start of a sequence of instructions to evaluate the filter function. */ Instruction getFilterClause() { cil_handler_filter(this, result) } - override int getPushCount() { result=1 } + + override int getPushCount() { result = 1 } } /** A handler corresponding to a `catch` clause. */ -class CatchHandler extends Handler, @cil_catch_handler -{ - override string toString() { result="catch(" + getCaughtType().getName() + ") {...}" } - override int getPushCount() { result=1 } +class CatchHandler extends Handler, @cil_catch_handler { + override string toString() { result = "catch(" + getCaughtType().getName() + ") {...}" } + + override int getPushCount() { result = 1 } } /** A handler for memory faults. */ -class FaultHandler extends Handler, @cil_fault_handler -{ - override string toString() { result="fault {...}" } +class FaultHandler extends Handler, @cil_fault_handler { + override string toString() { result = "fault {...}" } } diff --git a/csharp/ql/src/semmle/code/cil/Instruction.qll b/csharp/ql/src/semmle/code/cil/Instruction.qll index 60d6962ad23..ca9e6744624 100644 --- a/csharp/ql/src/semmle/code/cil/Instruction.qll +++ b/csharp/ql/src/semmle/code/cil/Instruction.qll @@ -3,16 +3,13 @@ private import CIL /** An instruction. */ -class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction -{ - override string toString() { result=getIndex() + ": " + getOpcodeName() + getExtraStr() } +class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction { + override string toString() { result = getIndex() + ": " + getOpcodeName() + getExtraStr() } /** Gets the method containing this instruction. */ - override MethodImplementation getImplementation() { - cil_instruction(this, _, _, result) - } + override MethodImplementation getImplementation() { cil_instruction(this, _, _, result) } - override Method getMethod() { result=getImplementation().getMethod() } + override Method getMethod() { result = getImplementation().getMethod() } /** * Gets the index of this instruction. @@ -21,7 +18,7 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi int getIndex() { cil_instruction(this, _, result, _) } /** Gets the opcode of this instruction. */ - final int getOpcode() { cil_instruction(this,result,_,_) } + final int getOpcode() { cil_instruction(this, result, _, _) } /** Gets the opcode name of this instruction, for example `ldnull`. */ string getOpcodeName() { none() } @@ -30,9 +27,7 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi string getExtra() { none() } private string getExtraStr() { - if exists(getExtra()) - then result = " " + getExtra() - else result = "" + if exists(getExtra()) then result = " " + getExtra() else result = "" } /** Gets the declaration accessed by this instruction, if any. */ @@ -40,11 +35,9 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi /** Gets a successor instruction to this instruction. */ override Instruction getASuccessorType(FlowType t) { - t instanceof NormalFlow - and - canFlowNext() - and - result = this.getImplementation().getInstruction(getIndex()+1) + t instanceof NormalFlow and + canFlowNext() and + result = this.getImplementation().getInstruction(getIndex() + 1) } /** Holds if this instruction passes control flow into the next instruction. */ @@ -54,22 +47,20 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi * Gets the `i`th handler that applies to this instruction. * Indexed from 0. */ - Handler getHandler(int i) - { - result.isInScope(this) - and - result.getIndex() = rank[i+1](int hi | exists(Handler h | h.isInScope(this) and hi=h.getIndex())) + Handler getHandler(int i) { + result.isInScope(this) and + result.getIndex() = rank[i + 1](int hi | + exists(Handler h | h.isInScope(this) and hi = h.getIndex()) + ) } - override Type getType() { result=ControlFlowNode.super.getType() } + override Type getType() { result = ControlFlowNode.super.getType() } override Location getALocation() { - cil_instruction_location(this, result) // The source code, if available + cil_instruction_location(this, result) // The source code, if available or - result = getImplementation().getLocation() // The containing assembly + result = getImplementation().getLocation() // The containing assembly } - override Location getLocation() { - result = Element.super.getLocation() - } + override Location getLocation() { result = Element.super.getLocation() } } diff --git a/csharp/ql/src/semmle/code/cil/InstructionGroups.qll b/csharp/ql/src/semmle/code/cil/InstructionGroups.qll index ecda6d50cdd..2e547e5d35c 100644 --- a/csharp/ql/src/semmle/code/cil/InstructionGroups.qll +++ b/csharp/ql/src/semmle/code/cil/InstructionGroups.qll @@ -10,49 +10,56 @@ private import dotnet * An instruction that pushes a value onto the stack. */ class Expr extends DotNet::Expr, Instruction, @cil_expr { - override int getPushCount() { result=1 } - override Type getType() { result=Instruction.super.getType() } - override Method getEnclosingCallable() { result=getImplementation().getMethod() } + override int getPushCount() { result = 1 } + + override Type getType() { result = Instruction.super.getType() } + + override Method getEnclosingCallable() { result = getImplementation().getMethod() } /** * The "parent" of a CIL expression is taken to be the instruction * that consumes the value pushed by this instruction. */ - override Expr getParent() { this=result.getAnOperand() } + override Expr getParent() { this = result.getAnOperand() } } /** An instruction that changes control flow. */ class Branch extends Instruction, @cil_jump { /** Gets the instruction that is jumped to. */ Instruction getTarget() { cil_jump(this, result) } - override string getExtra() { result=getTarget().getIndex() + ":" } + + override string getExtra() { result = getTarget().getIndex() + ":" } } /** An instruction that unconditionally jumps to another instruction. */ class UnconditionalBranch extends Branch, @cil_unconditional_jump { - override Instruction getASuccessorType(FlowType t) { t instanceof NormalFlow and result=getTarget() } + override Instruction getASuccessorType(FlowType t) { + t instanceof NormalFlow and result = getTarget() + } + override predicate canFlowNext() { none() } } /** An instruction that jumps to a target based on a condition. */ class ConditionalBranch extends Branch, @cil_conditional_jump { override Instruction getASuccessorType(FlowType t) { - t instanceof TrueFlow and result = getTarget() or - t instanceof FalseFlow and result = getImplementation().getInstruction(getIndex()+1) + t instanceof TrueFlow and result = getTarget() + or + t instanceof FalseFlow and result = getImplementation().getInstruction(getIndex() + 1) } - override int getPushCount() { result=0 } + + override int getPushCount() { result = 0 } } /** An expression with two operands. */ -class BinaryExpr extends Expr, @cil_binary_expr { - override int getPopCount() { result=2 } -} +class BinaryExpr extends Expr, @cil_binary_expr { override int getPopCount() { result = 2 } } /** An expression with one operand. */ class UnaryExpr extends Expr, @cil_unary_expr { - override int getPopCount() { result=1 } + override int getPopCount() { result = 1 } + /** Gets the operand of this unary expression. */ - Expr getOperand() { result=getOperand(0) } + Expr getOperand() { result = getOperand(0) } } /** A binary expression that compares two values. */ @@ -63,10 +70,16 @@ class ComparisonOperation extends BinaryExpr, @cil_comparison_operation { /** A binary arithmetic expression. */ class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation { override Type getType() { - exists(Type t0, Type t1 | t0=getOperand(0).getType().getUnderlyingType() and t1=getOperand(1).getType().getUnderlyingType() | - t0=t1 and result=t0 or - t0.getConversionIndex() < t1.getConversionIndex() and result=t1 or - t0.getConversionIndex() > t1.getConversionIndex() and result=t0) + exists(Type t0, Type t1 | + t0 = getOperand(0).getType().getUnderlyingType() and + t1 = getOperand(1).getType().getUnderlyingType() + | + t0 = t1 and result = t0 + or + t0.getConversionIndex() < t1.getConversionIndex() and result = t1 + or + t0.getConversionIndex() > t1.getConversionIndex() and result = t0 + ) } } @@ -85,16 +98,14 @@ class UnaryBitwiseOperation extends UnaryExpr, @cil_unary_bitwise_operation { /** A unary expression that converts a value from one primitive type to another. */ class Conversion extends UnaryExpr, @cil_conversion_operation { /** Gets the expression being converted. */ - Expr getExpr() { result=getOperand(0) } + Expr getExpr() { result = getOperand(0) } } /** A branch that leaves the scope of a `Handler`. */ -class Leave extends UnconditionalBranch, @cil_leave_any { -} +class Leave extends UnconditionalBranch, @cil_leave_any { } /** An expression that pushes a literal value onto the stack. */ -class Literal extends DotNet::Literal, Expr, @cil_literal -{ +class Literal extends DotNet::Literal, Expr, @cil_literal { /** Gets the pushed value. */ override string getValue() { cil_value(this, result) } @@ -104,73 +115,74 @@ class Literal extends DotNet::Literal, Expr, @cil_literal /** An integer literal. */ class IntLiteral extends Literal, @cil_ldc_i { override string getExtra() { none() } + override IntType getType() { exists(result) } } /** An expression that pushes a `float`/`Single`. */ -class FloatLiteral extends Literal, @cil_ldc_r { -} +class FloatLiteral extends Literal, @cil_ldc_r { } /** An expression that pushes a `null` value onto the stack. */ -class NullLiteral extends Literal, @cil_ldnull { -} +class NullLiteral extends Literal, @cil_ldnull { } /** A branch with one operand. */ class UnaryBranch extends ConditionalBranch, @cil_unary_jump { - override int getPopCount() { result=1 } - override int getPushCount() { result=0 } + override int getPopCount() { result = 1 } + + override int getPushCount() { result = 0 } } /** A branch with two operands. */ class BinaryBranch extends ConditionalBranch, @cil_binary_jump { - override int getPopCount() { result=2 } - override int getPushCount() { result=0 } + override int getPopCount() { result = 2 } + + override int getPushCount() { result = 0 } } /** A call. */ class Call extends Expr, DotNet::Call, @cil_call_any { - /** Gets the method that is called. */ override Method getTarget() { cil_access(this, result) } - override Method getARuntimeTarget() { - result = getTarget().getAnOverrider*() - } + override Method getARuntimeTarget() { result = getTarget().getAnOverrider*() } - override string getExtra() { result=getTarget().getQualifiedName() } + override string getExtra() { result = getTarget().getQualifiedName() } /** * Gets the return type of the call. Methods that do not return a value * return the `void` type, `System.Void`, although the value of `getPushCount` is * 0 in this case. */ - override Type getType() { result=getTarget().getReturnType() } + override Type getType() { result = getTarget().getReturnType() } // The number of items popped/pushed from the stack // depends on the target of the call. - override int getPopCount() { result=getTarget().getCallPopCount() } - override int getPushCount() { result=getTarget().getCallPushCount() } + override int getPopCount() { result = getTarget().getCallPopCount() } + + override int getPushCount() { result = getTarget().getCallPushCount() } /** * Holds if this is a "tail call", meaning that control does not return to the * calling method. */ predicate isTailCall() { - getImplementation().getInstruction(getIndex()-1) instanceof Opcodes::Tail + getImplementation().getInstruction(getIndex() - 1) instanceof Opcodes::Tail } /** Holds if this call is virtual and could go to an overriding method. */ predicate isVirtual() { none() } - override Expr getRawArgument(int i) { result=getOperand(getPopCount() - i - 1) } + override Expr getRawArgument(int i) { result = getOperand(getPopCount() - i - 1) } /** Gets the qualifier of this call, if any. */ - Expr getQualifier() { result=getRawArgument(0) and not getTarget().isStatic() } + Expr getQualifier() { result = getRawArgument(0) and not getTarget().isStatic() } override Expr getArgument(int i) { if getTarget().isStatic() - then result=getRawArgument(i) - else (result=getRawArgument(i+1) and i>=0) + then result = getRawArgument(i) + else ( + result = getRawArgument(i + 1) and i >= 0 + ) } override Expr getArgumentForParameter(DotNet::Parameter param) { @@ -183,24 +195,20 @@ class Call extends Expr, DotNet::Call, @cil_call_any { /** A tail call. */ class TailCall extends Call { TailCall() { this.isTailCall() } + override predicate canFlowNext() { none() } } /** A call to a static target. */ -class StaticCall extends Call { - StaticCall() { not this.isVirtual() } -} +class StaticCall extends Call { StaticCall() { not this.isVirtual() } } /** A call to a virtual target. */ -class VirtualCall extends Call { - VirtualCall() { this.isVirtual() } -} +class VirtualCall extends Call { VirtualCall() { this.isVirtual() } } /** A read of an array element. */ class ReadArrayElement extends BinaryExpr, @cil_read_array { - /** Gets the array being read. */ - Expr getArray() { result=getOperand(1) } + Expr getArray() { result = getOperand(1) } /** Gets the index into the array. */ Expr getArrayIndex() { result = getOperand(0) } @@ -208,34 +216,36 @@ class ReadArrayElement extends BinaryExpr, @cil_read_array { /** A write of an array element. */ class WriteArrayElement extends Instruction, @cil_write_array { - override int getPushCount() { result=0 } - override int getPopCount() { result=3 } + override int getPushCount() { result = 0 } + + override int getPopCount() { result = 3 } } /** A `return` statement. */ class Return extends Instruction, @cil_ret { /** Gets the expression being returned, if any. */ - Expr getExpr() { result=getOperand(0) } + Expr getExpr() { result = getOperand(0) } + override predicate canFlowNext() { none() } } /** A `throw` statement. */ class Throw extends Instruction, DotNet::Throw, @cil_throw_any { - override Expr getExpr() { result=getOperand(0) } + override Expr getExpr() { result = getOperand(0) } + override predicate canFlowNext() { none() } } /** Stores a value at an address/location. */ class StoreIndirect extends Instruction, @cil_stind { - override int getPopCount() { result=2 } + override int getPopCount() { result = 2 } /** Gets the location to store the value at. */ - Expr getAddress() { result=getOperand(1) } + Expr getAddress() { result = getOperand(1) } /** Gets the value to store. */ - Expr getExpr() { result=getOperand(0) } + Expr getExpr() { result = getOperand(0) } } /** Loads a value from an address/location. */ -class LoadIndirect extends UnaryExpr, @cil_ldind { -} +class LoadIndirect extends UnaryExpr, @cil_ldind { } diff --git a/csharp/ql/src/semmle/code/cil/Instructions.qll b/csharp/ql/src/semmle/code/cil/Instructions.qll index 50ab98b069a..16e26b906aa 100644 --- a/csharp/ql/src/semmle/code/cil/Instructions.qll +++ b/csharp/ql/src/semmle/code/cil/Instructions.qll @@ -5,574 +5,626 @@ private import CIL private import semmle.code.dotnet.Variable as DotNet -module Opcodes -{ +module Opcodes { // Literals - class Ldc_i4_m1 extends IntLiteral, @cil_ldc_i4_m1 { override string getOpcodeName() { result = "ldc.i4.m1" } - override string getValue() { result="-1" } + + override string getValue() { result = "-1" } } class Ldc_i4_0 extends IntLiteral, @cil_ldc_i4_0 { override string getOpcodeName() { result = "ldc.i4.0" } - override string getValue() { result="0" } + + override string getValue() { result = "0" } } class Ldc_i4_1 extends IntLiteral, @cil_ldc_i4_1 { override string getOpcodeName() { result = "ldc.i4.1" } - override string getValue() { result="1" } + + override string getValue() { result = "1" } } class Ldc_i4_2 extends IntLiteral, @cil_ldc_i4_2 { override string getOpcodeName() { result = "ldc.i4.2" } - override string getValue() { result="2" } + + override string getValue() { result = "2" } } class Ldc_i4_3 extends IntLiteral, @cil_ldc_i4_3 { override string getOpcodeName() { result = "ldc.i4.3" } - override string getValue() { result="3" } + + override string getValue() { result = "3" } } class Ldc_i4_4 extends IntLiteral, @cil_ldc_i4_4 { override string getOpcodeName() { result = "ldc.i4.4" } - override string getValue() { result="4" } + + override string getValue() { result = "4" } } class Ldc_i4_5 extends IntLiteral, @cil_ldc_i4_5 { override string getOpcodeName() { result = "ldc.i4.5" } - override string getValue() { result="5" } + + override string getValue() { result = "5" } } class Ldc_i4_6 extends IntLiteral, @cil_ldc_i4_6 { override string getOpcodeName() { result = "ldc.i4.6" } - override string getValue() { result="6" } + + override string getValue() { result = "6" } } class Ldc_i4_7 extends IntLiteral, @cil_ldc_i4_7 { override string getOpcodeName() { result = "ldc.i4.7" } - override string getValue() { result="7" } + + override string getValue() { result = "7" } } - class Ldc_i4_8 extends IntLiteral, @cil_ldc_i4_8 { + class Ldc_i4_8 extends IntLiteral, @cil_ldc_i4_8 { override string getOpcodeName() { result = "ldc.i4.8" } - override string getValue() { result="8" } + + override string getValue() { result = "8" } } class Ldc_i4 extends IntLiteral, @cil_ldc_i4 { override string getOpcodeName() { result = "ldc.i4" } - override string getExtra() { result=getValue() } + + override string getExtra() { result = getValue() } } class Ldc_i8 extends IntLiteral, @cil_ldc_i8 { override string getOpcodeName() { result = "ldc.i8" } - override string getExtra() { result=getValue() } + + override string getExtra() { result = getValue() } } class Ldc_i4_s extends IntLiteral, @cil_ldc_i4_s { override string getOpcodeName() { result = "ldc.i4.s" } - override string getExtra() { result=getValue() } + + override string getExtra() { result = getValue() } } class Ldnull extends Literal, @cil_ldnull { override string getOpcodeName() { result = "ldnull" } - override string getValue() { result="null" } + + override string getValue() { result = "null" } + override string getExtra() { none() } + override Type getType() { result instanceof ObjectType } } class Ldc_r4 extends FloatLiteral, @cil_ldc_r4 { override string getOpcodeName() { result = "ldc.r4" } - override string getExtra() { result=getValue() } + + override string getExtra() { result = getValue() } + override Type getType() { result instanceof FloatType } } class Ldc_r8 extends FloatLiteral, @cil_ldc_r8 { override string getOpcodeName() { result = "ldc.r8" } - override string getExtra() { result=getValue() } + + override string getExtra() { result = getValue() } + override Type getType() { result instanceof DoubleType } } // Arithmetic operations - class Add extends BinaryArithmeticExpr, @cil_add { - override string getOpcodeName() { result="add" } + override string getOpcodeName() { result = "add" } } class Add_ovf extends BinaryArithmeticExpr, @cil_add_ovf { - override string getOpcodeName() { result="add.ovf" } + override string getOpcodeName() { result = "add.ovf" } } class Add_ovf_un extends BinaryArithmeticExpr, @cil_add_ovf_un { - override string getOpcodeName() { result="add.ovf.un" } + override string getOpcodeName() { result = "add.ovf.un" } } class Sub extends BinaryArithmeticExpr, @cil_sub { - override string getOpcodeName() { result="sub" } + override string getOpcodeName() { result = "sub" } } class Sub_ovf extends BinaryArithmeticExpr, @cil_sub_ovf { - override string getOpcodeName() { result="sub.ovf" } + override string getOpcodeName() { result = "sub.ovf" } } class Sub_ovf_un extends BinaryArithmeticExpr, @cil_sub_ovf_un { - override string getOpcodeName() { result="sub.ovf.un" } + override string getOpcodeName() { result = "sub.ovf.un" } } class Mul extends BinaryArithmeticExpr, @cil_mul { - override string getOpcodeName() { result="mul" } + override string getOpcodeName() { result = "mul" } } class Mul_ovf extends BinaryArithmeticExpr, @cil_mul_ovf { - override string getOpcodeName() { result="mul.ovf" } + override string getOpcodeName() { result = "mul.ovf" } } class Mul_ovf_un extends BinaryArithmeticExpr, @cil_mul_ovf_un { - override string getOpcodeName() { result="mul.ovf.un" } + override string getOpcodeName() { result = "mul.ovf.un" } } class Div extends BinaryArithmeticExpr, @cil_div { - override string getOpcodeName() { result="div" } + override string getOpcodeName() { result = "div" } } class Div_un extends BinaryArithmeticExpr, @cil_div_un { - override string getOpcodeName() { result="div.un" } + override string getOpcodeName() { result = "div.un" } } class Rem extends BinaryArithmeticExpr, @cil_rem { - override string getOpcodeName() { result="rem" } + override string getOpcodeName() { result = "rem" } } class Rem_un extends BinaryArithmeticExpr, @cil_rem_un { - override string getOpcodeName() { result="rem.un" } + override string getOpcodeName() { result = "rem.un" } } class Neg extends UnaryExpr, @cil_neg { - override string getOpcodeName() { result="neg" } - override NumericType getType() { result=getOperand(0).getType() } + override string getOpcodeName() { result = "neg" } + + override NumericType getType() { result = getOperand(0).getType() } } // Binary operations - class And extends BinaryBitwiseOperation, @cil_and { - override string getOpcodeName() { result="and" } + override string getOpcodeName() { result = "and" } } class Or extends BinaryBitwiseOperation, @cil_or { - override string getOpcodeName() { result="or" } + override string getOpcodeName() { result = "or" } } class Xor extends BinaryBitwiseOperation, @cil_xor { - override string getOpcodeName() { result="xor" } + override string getOpcodeName() { result = "xor" } } class Not extends UnaryBitwiseOperation, @cil_not { - override string getOpcodeName() { result="not" } + override string getOpcodeName() { result = "not" } } class Shl extends BinaryBitwiseOperation, @cil_shl { - override string getOpcodeName() { result="shl" } + override string getOpcodeName() { result = "shl" } } class Shr extends BinaryBitwiseOperation, @cil_shr { - override string getOpcodeName() { result="shr" } + override string getOpcodeName() { result = "shr" } } class Shr_un extends BinaryBitwiseOperation, @cil_shr_un { - override string getOpcodeName() { result="shr.un" } + override string getOpcodeName() { result = "shr.un" } } // Binary comparison operations - class Ceq extends ComparisonOperation, @cil_ceq { - override string getOpcodeName() { result="ceq" } + override string getOpcodeName() { result = "ceq" } } class Pop extends Instruction, @cil_pop { - override string getOpcodeName() { result="pop" } - override int getPopCount() { result=1 } + override string getOpcodeName() { result = "pop" } + + override int getPopCount() { result = 1 } } class Dup extends Expr, @cil_dup { - override string getOpcodeName() { result="dup" } - override int getPopCount() { result=1 } - override int getPushCount() { result=2 } // This is the only instruction that pushes 2 items - override Type getType() { result=getOperand(0).getType() } + override string getOpcodeName() { result = "dup" } + + override int getPopCount() { result = 1 } + + override int getPushCount() { result = 2 } // This is the only instruction that pushes 2 items + + override Type getType() { result = getOperand(0).getType() } } class Ret extends Return, @cil_ret { - override string getOpcodeName() { result="ret" } + override string getOpcodeName() { result = "ret" } + override predicate canFlowNext() { none() } - override int getPopCount() - { - if getImplementation().getMethod().returnsVoid() - then result=0 - else result=1 + + override int getPopCount() { + if getImplementation().getMethod().returnsVoid() then result = 0 else result = 1 } } - class Nop extends Instruction, @cil_nop { - override string getOpcodeName() { result="nop" } - } + class Nop extends Instruction, @cil_nop { override string getOpcodeName() { result = "nop" } } class Ldstr extends Literal, @cil_ldstr { - override string getOpcodeName() { result="ldstr" } + override string getOpcodeName() { result = "ldstr" } + override string getExtra() { result = "\"" + getValue() + "\"" } + override Type getType() { result instanceof StringType } } // Control flow - class Br extends UnconditionalBranch, @cil_br { - override string getOpcodeName() { result="br" } + override string getOpcodeName() { result = "br" } } class Br_s extends UnconditionalBranch, @cil_br_s { - override string getOpcodeName() { result="br.s" } + override string getOpcodeName() { result = "br.s" } } class Brfalse_s extends UnaryBranch, @cil_brfalse_s { - override string getOpcodeName() { result="brfalse.s" } + override string getOpcodeName() { result = "brfalse.s" } } class Brfalse extends UnaryBranch, @cil_brfalse { - override string getOpcodeName() { result="brfalse" } + override string getOpcodeName() { result = "brfalse" } } class Brtrue_s extends UnaryBranch, @cil_brtrue_s { - override string getOpcodeName() { result="brtrue.s" } + override string getOpcodeName() { result = "brtrue.s" } } class Brtrue extends UnaryBranch, @cil_brtrue { - override string getOpcodeName() { result="brtrue" } + override string getOpcodeName() { result = "brtrue" } } class Blt_s extends BinaryBranch, @cil_blt_s { - override string getOpcodeName() { result="blt.s" } + override string getOpcodeName() { result = "blt.s" } } - class Blt extends BinaryBranch, @cil_blt { - override string getOpcodeName() { result="blt" } - } + class Blt extends BinaryBranch, @cil_blt { override string getOpcodeName() { result = "blt" } } class Blt_un_s extends BinaryBranch, @cil_blt_un_s { - override string getOpcodeName() { result="blt.un.s" } + override string getOpcodeName() { result = "blt.un.s" } } class Blt_un extends BinaryBranch, @cil_blt_un { - override string getOpcodeName() { result="blt.un" } + override string getOpcodeName() { result = "blt.un" } } class Bgt_un extends BinaryBranch, @cil_bgt_un { - override string getOpcodeName() { result="bgt.un" } + override string getOpcodeName() { result = "bgt.un" } } class Ble_un_s extends BinaryBranch, @cil_ble_un_s { - override string getOpcodeName() { result="ble.un.s" } + override string getOpcodeName() { result = "ble.un.s" } } class Ble_un extends BinaryBranch, @cil_ble_un { - override string getOpcodeName() { result="ble.un" } + override string getOpcodeName() { result = "ble.un" } } class Bge_s extends BinaryBranch, @cil_bge_s { - override string getOpcodeName() { result="bge.s" } + override string getOpcodeName() { result = "bge.s" } } class Bge_un extends BinaryBranch, @cil_bge_un { - override string getOpcodeName() { result="bge.un" } + override string getOpcodeName() { result = "bge.un" } } - class Bge extends BinaryBranch, @cil_bge { - override string getOpcodeName() { result="bge" } - } + class Bge extends BinaryBranch, @cil_bge { override string getOpcodeName() { result = "bge" } } class Bne_un_s extends BinaryBranch, @cil_bne_un_s { - override string getOpcodeName() { result="bne.un.s" } + override string getOpcodeName() { result = "bne.un.s" } } class Bne_un extends BinaryBranch, @cil_bne_un { - override string getOpcodeName() { result="bne.un" } + override string getOpcodeName() { result = "bne.un" } } - class Beq extends BinaryBranch, @cil_beq { - override string getOpcodeName() { result="beq" } - } + class Beq extends BinaryBranch, @cil_beq { override string getOpcodeName() { result = "beq" } } class Beq_s extends BinaryBranch, @cil_beq_s { - override string getOpcodeName() { result="beq.s" } + override string getOpcodeName() { result = "beq.s" } } class Ble_s extends BinaryBranch, @cil_ble_s { - override string getOpcodeName() { result="ble.s" } + override string getOpcodeName() { result = "ble.s" } } - class Ble extends BinaryBranch, @cil_ble { - override string getOpcodeName() { result="ble" } - } + class Ble extends BinaryBranch, @cil_ble { override string getOpcodeName() { result = "ble" } } class Bgt_s extends BinaryBranch, @cil_bgt_s { - override string getOpcodeName() { result="bgt.s" } + override string getOpcodeName() { result = "bgt.s" } } - class Bgt extends BinaryBranch, @cil_bgt { - override string getOpcodeName() { result="bgt" } - } + class Bgt extends BinaryBranch, @cil_bgt { override string getOpcodeName() { result = "bgt" } } class Bgt_in_s extends BinaryBranch, @cil_bgt_un_s { - override string getOpcodeName() { result="bgt.un.s" } + override string getOpcodeName() { result = "bgt.un.s" } } class Bge_in_s extends BinaryBranch, @cil_bge_un_s { - override string getOpcodeName() { result="bge.un.s" } + override string getOpcodeName() { result = "bge.un.s" } } class Switch extends ConditionalBranch, @cil_switch { - override string getOpcodeName() { result="switch" } + override string getOpcodeName() { result = "switch" } + /** Gets the `n`th jump target of this switch. */ Instruction getTarget(int n) { cil_switch(this, n, result) } + override Instruction getASuccessorType(FlowType t) { t instanceof NormalFlow and - (result=getTarget(_) or result=getImplementation().getInstruction(getIndex()+1)) + (result = getTarget(_) or result = getImplementation().getInstruction(getIndex() + 1)) + } + + override string getExtra() { + result = concat(int n | exists(getTarget(n)) | getTarget(n).getIndex() + ":", " ") } - override string getExtra() { result = concat(int n | exists(getTarget(n)) | getTarget(n).getIndex()+":", " ") } } - class Leave_ extends Leave, @cil_leave { - override string getOpcodeName() { result="leave" } - } + class Leave_ extends Leave, @cil_leave { override string getOpcodeName() { result = "leave" } } class Leave_s extends Leave, @cil_leave_s { - override string getOpcodeName() { result="leave.s" } + override string getOpcodeName() { result = "leave.s" } } class Endfilter extends Instruction, @cil_endfilter { - override string getOpcodeName() { result="endfilter" } + override string getOpcodeName() { result = "endfilter" } } class Endfinally extends Instruction, @cil_endfinally { - override string getOpcodeName() { result="endfinally" } + override string getOpcodeName() { result = "endfinally" } + override predicate canFlowNext() { none() } } // Comparisons (not jumps) - class Cgt_un extends ComparisonOperation, @cil_cgt_un { - override string getOpcodeName() { result="cgt.un" } + override string getOpcodeName() { result = "cgt.un" } } class Cgt extends ComparisonOperation, @cil_cgt { - override string getOpcodeName() { result="cgt" } + override string getOpcodeName() { result = "cgt" } } class Clt_un extends ComparisonOperation, @cil_clt_un { - override string getOpcodeName() { result="cgt.un" } + override string getOpcodeName() { result = "cgt.un" } } class Clt extends ComparisonOperation, @cil_clt { - override string getOpcodeName() { result="clt" } + override string getOpcodeName() { result = "clt" } } // Calls - - class Call_ extends Call, @cil_call { - override string getOpcodeName() { result="call" } - } + class Call_ extends Call, @cil_call { override string getOpcodeName() { result = "call" } } class Callvirt extends Call, @cil_callvirt { - override string getOpcodeName() { result="callvirt" } + override string getOpcodeName() { result = "callvirt" } + override predicate isVirtual() { any() } } - class Tail extends Instruction, @cil_tail { - override string getOpcodeName() { result="tail." } - } + class Tail extends Instruction, @cil_tail { override string getOpcodeName() { result = "tail." } } class Jmp extends Call, @cil_jmp { - override string getOpcodeName() { result="jmp"} + override string getOpcodeName() { result = "jmp" } + override predicate isTailCall() { any() } } class Isinst extends UnaryExpr, @cil_isinst { - override string getOpcodeName() { result="isinst" } + override string getOpcodeName() { result = "isinst" } + override BoolType getType() { exists(result) } + /** Gets the type that is being tested against. */ - Type getTestedType() { result=getAccess() } - override string getExtra() { result=getTestedType().getQualifiedName() } + Type getTestedType() { result = getAccess() } + + override string getExtra() { result = getTestedType().getQualifiedName() } } class Castclass extends UnaryExpr, @cil_castclass { - override string getOpcodeName() { result="castclass" } - override Type getType() { result=getAccess() } + override string getOpcodeName() { result = "castclass" } + + override Type getType() { result = getAccess() } + /** Gets the type that is being cast to. */ - Type getTestedType() { result=getAccess() } - override string getExtra() { result=getTestedType().getQualifiedName() } + Type getTestedType() { result = getAccess() } + + override string getExtra() { result = getTestedType().getQualifiedName() } } // Locals - class Stloc_0 extends LocalVariableWriteAccess, @cil_stloc_0 { override string getOpcodeName() { result = "stloc.0" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(0) } } class Stloc_1 extends LocalVariableWriteAccess, @cil_stloc_1 { override string getOpcodeName() { result = "stloc.1" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(1) } } class Stloc_2 extends LocalVariableWriteAccess, @cil_stloc_2 { override string getOpcodeName() { result = "stloc.2" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(2) } } class Stloc_3 extends LocalVariableWriteAccess, @cil_stloc_3 { override string getOpcodeName() { result = "stloc.3" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(3) } } class Stloc_s extends LocalVariableWriteAccess, @cil_stloc_s { override string getOpcodeName() { result = "stloc.s" } + override LocalVariable getTarget() { cil_access(this, result) } } class Stloc extends LocalVariableWriteAccess, @cil_stloc { override string getOpcodeName() { result = "stloc" } + override LocalVariable getTarget() { cil_access(this, result) } } class Ldloc_0 extends LocalVariableReadAccess, @cil_ldloc_0 { override string getOpcodeName() { result = "ldloc.0" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(0) } } class Ldloc_1 extends LocalVariableReadAccess, @cil_ldloc_1 { override string getOpcodeName() { result = "ldloc.1" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(1) } } class Ldloc_2 extends LocalVariableReadAccess, @cil_ldloc_2 { override string getOpcodeName() { result = "ldloc.2" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(2) } } class Ldloc_3 extends LocalVariableReadAccess, @cil_ldloc_3 { override string getOpcodeName() { result = "ldloc.3" } + override LocalVariable getTarget() { result = getImplementation().getLocalVariable(3) } } class Ldloc_s extends LocalVariableReadAccess, @cil_ldloc_s { override string getOpcodeName() { result = "ldloc.s" } + override LocalVariable getTarget() { cil_access(this, result) } - override string getExtra() { result = "L"+ getTarget().getIndex() } + + override string getExtra() { result = "L" + getTarget().getIndex() } } class Ldloca_s extends LocalVariableReadAccess, ReadRefAccess, @cil_ldloca_s { override string getOpcodeName() { result = "ldloca.s" } + override LocalVariable getTarget() { cil_access(this, result) } - override string getExtra() { result = "L"+ getTarget().getIndex() } + + override string getExtra() { result = "L" + getTarget().getIndex() } } class Ldloc extends LocalVariableReadAccess, @cil_ldloc { override string getOpcodeName() { result = "ldloc" } + override LocalVariable getTarget() { cil_access(this, result) } - override string getExtra() { result = "L"+ getTarget().getIndex() } + + override string getExtra() { result = "L" + getTarget().getIndex() } } // Arguments - class Ldarg_0 extends ParameterReadAccess, @cil_ldarg_0 { - override string getOpcodeName() { result="ldarg.0" } - override Parameter getTarget() { result=getImplementation().getMethod().getRawParameter(0) } + override string getOpcodeName() { result = "ldarg.0" } + + override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(0) } } class Ldarg_1 extends ParameterReadAccess, @cil_ldarg_1 { - override string getOpcodeName() { result="ldarg.1" } - override Parameter getTarget() { result=getImplementation().getMethod().getRawParameter(1) } + override string getOpcodeName() { result = "ldarg.1" } + + override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(1) } } class Ldarg_2 extends ParameterReadAccess, @cil_ldarg_2 { - override string getOpcodeName() { result="ldarg.2" } - override Parameter getTarget() { result=getImplementation().getMethod().getRawParameter(2) } + override string getOpcodeName() { result = "ldarg.2" } + + override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(2) } } class Ldarg_3 extends ParameterReadAccess, @cil_ldarg_3 { - override string getOpcodeName() { result="ldarg.3" } - override Parameter getTarget() { result=getImplementation().getMethod().getRawParameter(3) } + override string getOpcodeName() { result = "ldarg.3" } + + override Parameter getTarget() { result = getImplementation().getMethod().getRawParameter(3) } } class Ldarg_s extends ParameterReadAccess, @cil_ldarg_s { - override string getOpcodeName() { result="ldarg.s" } + override string getOpcodeName() { result = "ldarg.s" } + override Parameter getTarget() { cil_access(this, result) } - override string getExtra() { result=this.getTarget().getIndex().toString() } + + override string getExtra() { result = this.getTarget().getIndex().toString() } } class Ldarg extends ParameterReadAccess, @cil_ldarg { - override string getOpcodeName() { result="ldarg" } + override string getOpcodeName() { result = "ldarg" } + override Parameter getTarget() { cil_access(this, result) } } class Ldarga_s extends ParameterReadAccess, ReadRefAccess, @cil_ldarga_s { - override string getOpcodeName() { result="ldarga.s" } + override string getOpcodeName() { result = "ldarga.s" } + override Parameter getTarget() { cil_access(this, result) } } class Starg_s extends ParameterWriteAccess, @cil_starg_s { - override string getOpcodeName() { result="starg.s" } + override string getOpcodeName() { result = "starg.s" } + override Parameter getTarget() { cil_access(this, result) } } // Fields - class Ldfld extends FieldReadAccess, @cil_ldfld { - override string getOpcodeName() { result="ldfld" } - override int getPopCount() { result=1 } - override Expr getQualifier() { result=getOperand(0) } + override string getOpcodeName() { result = "ldfld" } + + override int getPopCount() { result = 1 } + + override Expr getQualifier() { result = getOperand(0) } } class Ldflda extends FieldReadAccess, ReadRefAccess, @cil_ldflda { - override string getOpcodeName() { result="ldflda" } - override int getPopCount() { result=1 } - override Expr getQualifier() { result=getOperand(0) } + override string getOpcodeName() { result = "ldflda" } + + override int getPopCount() { result = 1 } + + override Expr getQualifier() { result = getOperand(0) } } class Ldsfld extends FieldReadAccess, @cil_ldsfld { - override string getOpcodeName() { result="ldsfld" } - override int getPopCount() { result=0 } + override string getOpcodeName() { result = "ldsfld" } + + override int getPopCount() { result = 0 } + override Expr getQualifier() { none() } } class Ldsflda extends FieldReadAccess, ReadRefAccess, @cil_ldsflda { - override string getOpcodeName() { result="ldsflda" } - override int getPopCount() { result=0 } + override string getOpcodeName() { result = "ldsflda" } + + override int getPopCount() { result = 0 } + override Expr getQualifier() { none() } } class Stfld extends FieldWriteAccess, @cil_stfld { - override string getOpcodeName() { result="stfld" } - override int getPopCount() { result=2 } - override Expr getQualifier() { result=getOperand(1) } - override Expr getExpr() { result=getOperand(0) } + override string getOpcodeName() { result = "stfld" } + + override int getPopCount() { result = 2 } + + override Expr getQualifier() { result = getOperand(1) } + + override Expr getExpr() { result = getOperand(0) } } class Stsfld extends FieldWriteAccess, @cil_stsfld { - override string getOpcodeName() { result="stsfld" } - override int getPopCount() { result=1 } + override string getOpcodeName() { result = "stsfld" } + + override int getPopCount() { result = 1 } + override Expr getQualifier() { none() } - override Expr getExpr() { result=getOperand(0) } + + override Expr getExpr() { result = getOperand(0) } } class Newobj extends Call, @cil_newobj { override string getOpcodeName() { result = "newobj" } - override int getPushCount() { result=1 } - override int getPopCount() { result=count(this.getARawTargetParameter())-1 } - override Type getType() { result=this.getTarget().getDeclaringType() } - override Expr getArgument(int i) { result=getRawArgument(i) } - pragma [noinline] - private Parameter getARawTargetParameter() { - result = this.getTarget().getARawParameter() - } + override int getPushCount() { result = 1 } + + override int getPopCount() { result = count(this.getARawTargetParameter()) - 1 } + + override Type getType() { result = this.getTarget().getDeclaringType() } + + override Expr getArgument(int i) { result = getRawArgument(i) } + + pragma[noinline] + private Parameter getARawTargetParameter() { result = this.getTarget().getARawParameter() } override Expr getArgumentForParameter(DotNet::Parameter param) { exists(int index | @@ -583,34 +635,41 @@ module Opcodes } class Initobj extends Instruction, @cil_initobj { - override string getOpcodeName() { result="initobj" } + override string getOpcodeName() { result = "initobj" } + override int getPopCount() { result = 1 } // ?? } class Box extends UnaryExpr, @cil_box { - override string getOpcodeName() { result="box" } - override Type getType() { result=getAccess() } + override string getOpcodeName() { result = "box" } + + override Type getType() { result = getAccess() } } class Unbox_any extends UnaryExpr, @cil_unbox_any { - override string getOpcodeName() { result="unbox.any" } - override Type getType() { result=getAccess() } + override string getOpcodeName() { result = "unbox.any" } + + override Type getType() { result = getAccess() } } class Unbox extends UnaryExpr, @cil_unbox { - override string getOpcodeName() { result="unbox" } - override Type getType() { result=getAccess() } + override string getOpcodeName() { result = "unbox" } + + override Type getType() { result = getAccess() } } class Ldobj extends UnaryExpr, @cil_ldobj { override string getOpcodeName() { result = "ldobj" } + /** Gets the type of the object. */ Type getTarget() { cil_access(this, result) } - override Type getType() { result=getAccess() } + + override Type getType() { result = getAccess() } } class Ldtoken extends Expr, @cil_ldtoken { - override string getOpcodeName() { result="ldtoken" } + override string getOpcodeName() { result = "ldtoken" } + // Not really sure what a type of a token is so use `object`. override ObjectType getType() { exists(result) } } @@ -621,443 +680,508 @@ module Opcodes class Throw_ extends Throw, @cil_throw { override string getOpcodeName() { result = "throw" } - override int getPopCount() { result=1 } + + override int getPopCount() { result = 1 } } class Rethrow extends Throw, @cil_rethrow { override string getOpcodeName() { result = "rethrow" } } - class Ldlen extends UnaryExpr, @cil_ldlen { override string getOpcodeName() { result = "ldlen" } + override IntType getType() { exists(result) } } // Arrays - class Newarr extends Expr, @cil_newarr { override string getOpcodeName() { result = "newarr" } - override int getPushCount() { result=1 } - override int getPopCount() { result=1 } + + override int getPushCount() { result = 1 } + + override int getPopCount() { result = 1 } + override Type getType() { // Note that this is technically wrong - it should be // result.(ArrayType).getElementType() = getAccess() // However the (ArrayType) may not be in the database. result = getAccess() } - override string getExtra() { result=getType().getQualifiedName() } + + override string getExtra() { result = getType().getQualifiedName() } } class Ldelem extends ReadArrayElement, @cil_ldelem { override string getOpcodeName() { result = "ldelem" } - override Type getType() { result=getAccess() } + + override Type getType() { result = getAccess() } } class Ldelem_ref extends ReadArrayElement, @cil_ldelem_ref { - override string getOpcodeName() { result="ldelem.ref" } - override Type getType() { result=getArray().getType() } + override string getOpcodeName() { result = "ldelem.ref" } + + override Type getType() { result = getArray().getType() } } class Ldelema extends ReadArrayElement, ReadRef, @cil_ldelema { - override string getOpcodeName() { result="ldelema" } - override Type getType() { result=getAccess() } + override string getOpcodeName() { result = "ldelema" } + + override Type getType() { result = getAccess() } } class Stelem_ref extends WriteArrayElement, @cil_stelem_ref { - override string getOpcodeName() { result="stelem.ref" } + override string getOpcodeName() { result = "stelem.ref" } } class Stelem extends WriteArrayElement, @cil_stelem { - override string getOpcodeName() { result="stelem" } + override string getOpcodeName() { result = "stelem" } } class Stelem_i extends WriteArrayElement, @cil_stelem_i { - override string getOpcodeName() { result="stelem.i" } + override string getOpcodeName() { result = "stelem.i" } } class Stelem_i1 extends WriteArrayElement, @cil_stelem_i1 { - override string getOpcodeName() { result="stelem.i1" } + override string getOpcodeName() { result = "stelem.i1" } } class Stelem_i2 extends WriteArrayElement, @cil_stelem_i2 { - override string getOpcodeName() { result="stelem.i2" } + override string getOpcodeName() { result = "stelem.i2" } } class Stelem_i4 extends WriteArrayElement, @cil_stelem_i4 { - override string getOpcodeName() { result="stelem.i4" } + override string getOpcodeName() { result = "stelem.i4" } } class Stelem_i8 extends WriteArrayElement, @cil_stelem_i8 { - override string getOpcodeName() { result="stelem.i8" } + override string getOpcodeName() { result = "stelem.i8" } } class Stelem_r4 extends WriteArrayElement, @cil_stelem_r4 { - override string getOpcodeName() { result="stelem.r4" } + override string getOpcodeName() { result = "stelem.r4" } } class Stelem_r8 extends WriteArrayElement, @cil_stelem_r8 { - override string getOpcodeName() { result="stelem.r8" } + override string getOpcodeName() { result = "stelem.r8" } } class Ldelem_i extends ReadArrayElement, @cil_ldelem_i { override string getOpcodeName() { result = "ldelem.i" } + override IntType getType() { exists(result) } } class Ldelem_i1 extends ReadArrayElement, @cil_ldelem_i1 { override string getOpcodeName() { result = "ldelem.i1" } + override SByteType getType() { exists(result) } } class Ldelem_i2 extends ReadArrayElement, @cil_ldelem_i2 { override string getOpcodeName() { result = "ldelem.i2" } + override ShortType getType() { exists(result) } } class Ldelem_i4 extends ReadArrayElement, @cil_ldelem_i4 { override string getOpcodeName() { result = "ldelem.i4" } + override IntType getType() { exists(result) } } class Ldelem_i8 extends ReadArrayElement, @cil_ldelem_i8 { override string getOpcodeName() { result = "ldelem.i8" } + override LongType getType() { exists(result) } } class Ldelem_r4 extends ReadArrayElement, @cil_ldelem_r4 { override string getOpcodeName() { result = "ldelem.r4" } + override FloatType getType() { exists(result) } } class Ldelem_r8 extends ReadArrayElement, @cil_ldelem_r8 { override string getOpcodeName() { result = "ldelem.r8" } + override DoubleType getType() { exists(result) } } class Ldelem_u1 extends ReadArrayElement, @cil_ldelem_u1 { override string getOpcodeName() { result = "ldelem.u1" } + override ByteType getType() { exists(result) } } class Ldelem_u2 extends ReadArrayElement, @cil_ldelem_u2 { override string getOpcodeName() { result = "ldelem.u2" } + override UShortType getType() { exists(result) } } class Ldelem_u4 extends ReadArrayElement, @cil_ldelem_u4 { override string getOpcodeName() { result = "ldelem.u4" } + override UIntType getType() { exists(result) } } // Conversions - class Conv_i extends Conversion, @cil_conv_i { - override string getOpcodeName() { result="conv.i" } + override string getOpcodeName() { result = "conv.i" } + override IntType getType() { exists(result) } } class Conv_ovf_i extends Conversion, @cil_conv_ovf_i { - override string getOpcodeName() { result="conv.ovf.i" } + override string getOpcodeName() { result = "conv.ovf.i" } + override IntType getType() { exists(result) } } class Conv_ovf_i_un extends Conversion, @cil_conv_ovf_i_un { - override string getOpcodeName() { result="conv.ovf.i.un" } + override string getOpcodeName() { result = "conv.ovf.i.un" } + override UIntType getType() { exists(result) } } class Conv_i1 extends Conversion, @cil_conv_i1 { - override string getOpcodeName() { result="conv.i1" } + override string getOpcodeName() { result = "conv.i1" } + override SByteType getType() { exists(result) } } class Conv_ovf_i1 extends Conversion, @cil_conv_ovf_i1 { - override string getOpcodeName() { result="conv.ovf.i1" } + override string getOpcodeName() { result = "conv.ovf.i1" } + override SByteType getType() { exists(result) } } class Conv_ovf_i1_un extends Conversion, @cil_conv_ovf_i1_un { - override string getOpcodeName() { result="conv.ovf.i1.un" } + override string getOpcodeName() { result = "conv.ovf.i1.un" } + override SByteType getType() { exists(result) } } class Conv_i2 extends Conversion, @cil_conv_i2 { - override string getOpcodeName() { result="conv.i2" } + override string getOpcodeName() { result = "conv.i2" } + override ShortType getType() { exists(result) } } class Conv_ovf_i2 extends Conversion, @cil_conv_ovf_i2 { - override string getOpcodeName() { result="conv.ovf.i2" } + override string getOpcodeName() { result = "conv.ovf.i2" } + override ShortType getType() { exists(result) } } class Conv_ovf_i2_un extends Conversion, @cil_conv_ovf_i2_un { - override string getOpcodeName() { result="conv.ovf.i2.un" } + override string getOpcodeName() { result = "conv.ovf.i2.un" } + override ShortType getType() { exists(result) } } class Conv_i4 extends Conversion, @cil_conv_i4 { - override string getOpcodeName() { result="conv.i4" } + override string getOpcodeName() { result = "conv.i4" } + override IntType getType() { exists(result) } } class Conv_ovf_i4 extends Conversion, @cil_conv_ovf_i4 { - override string getOpcodeName() { result="conv.ovf.i4" } + override string getOpcodeName() { result = "conv.ovf.i4" } + override IntType getType() { exists(result) } } class Conv_ovf_i4_un extends Conversion, @cil_conv_ovf_i4_un { - override string getOpcodeName() { result="conv.ovf.i4.un" } + override string getOpcodeName() { result = "conv.ovf.i4.un" } + override IntType getType() { exists(result) } } class Conv_i8 extends Conversion, @cil_conv_i8 { - override string getOpcodeName() { result="conv.i8" } + override string getOpcodeName() { result = "conv.i8" } + override LongType getType() { exists(result) } } class Conv_ovf_i8 extends Conversion, @cil_conv_ovf_i8 { - override string getOpcodeName() { result="conv.ovf.i8" } + override string getOpcodeName() { result = "conv.ovf.i8" } + override LongType getType() { exists(result) } } class Conv_ovf_i8_un extends Conversion, @cil_conv_ovf_i8_un { - override string getOpcodeName() { result="conv.ovf.i8.un" } + override string getOpcodeName() { result = "conv.ovf.i8.un" } + override LongType getType() { exists(result) } } // Unsigned conversions - class Conv_u extends Conversion, @cil_conv_u { - override string getOpcodeName() { result="conv.u" } + override string getOpcodeName() { result = "conv.u" } + override UIntType getType() { exists(result) } } class Conv_ovf_u extends Conversion, @cil_conv_ovf_u { - override string getOpcodeName() { result="conv.ovf.u" } + override string getOpcodeName() { result = "conv.ovf.u" } + override UIntType getType() { exists(result) } } class Conv_ovf_u_un extends Conversion, @cil_conv_ovf_u_un { - override string getOpcodeName() { result="conv.ovf.u.un" } + override string getOpcodeName() { result = "conv.ovf.u.un" } + override UIntType getType() { exists(result) } } class Conv_u1 extends Conversion, @cil_conv_u1 { - override string getOpcodeName() { result="conv.u1" } + override string getOpcodeName() { result = "conv.u1" } + override ByteType getType() { exists(result) } } class Conv_ovf_u1 extends Conversion, @cil_conv_ovf_u1 { - override string getOpcodeName() { result="conv.ovf.u1" } + override string getOpcodeName() { result = "conv.ovf.u1" } + override ByteType getType() { exists(result) } } class Conv_ovf_u1_un extends Conversion, @cil_conv_ovf_u1_un { - override string getOpcodeName() { result="conv.ovf.u1.un" } + override string getOpcodeName() { result = "conv.ovf.u1.un" } + override ByteType getType() { exists(result) } } class Conv_u2 extends Conversion, @cil_conv_u2 { - override string getOpcodeName() { result="conv.u2" } + override string getOpcodeName() { result = "conv.u2" } + override UShortType getType() { exists(result) } } class Conv_ovf_u2 extends Conversion, @cil_conv_ovf_u2 { - override string getOpcodeName() { result="conv.ovf.u2" } + override string getOpcodeName() { result = "conv.ovf.u2" } + override UShortType getType() { exists(result) } } class Conv_ovf_u2_un extends Conversion, @cil_conv_ovf_u2_un { - override string getOpcodeName() { result="conv.ovf.u2.un" } + override string getOpcodeName() { result = "conv.ovf.u2.un" } + override UShortType getType() { exists(result) } } class Conv_u4 extends Conversion, @cil_conv_u4 { - override string getOpcodeName() { result="conv.u4" } + override string getOpcodeName() { result = "conv.u4" } + override UIntType getType() { exists(result) } } class Conv_ovf_u4 extends Conversion, @cil_conv_ovf_u4 { - override string getOpcodeName() { result="conv.ovf.u4" } + override string getOpcodeName() { result = "conv.ovf.u4" } + override UIntType getType() { exists(result) } } class Conv_ovf_u4_un extends Conversion, @cil_conv_ovf_u4_un { - override string getOpcodeName() { result="conv.ovf.u4.un" } + override string getOpcodeName() { result = "conv.ovf.u4.un" } + override UIntType getType() { exists(result) } } class Conv_u8 extends Conversion, @cil_conv_u8 { - override string getOpcodeName() { result="conv.u8" } + override string getOpcodeName() { result = "conv.u8" } + override ULongType getType() { exists(result) } } class Conv_ovf_u8 extends Conversion, @cil_conv_ovf_u8 { - override string getOpcodeName() { result="conv.ovf.u8" } + override string getOpcodeName() { result = "conv.ovf.u8" } + override ULongType getType() { exists(result) } } class Conv_ovf_u8_un extends Conversion, @cil_conv_ovf_u8_un { - override string getOpcodeName() { result="conv.ovf.u8.un" } + override string getOpcodeName() { result = "conv.ovf.u8.un" } + override ULongType getType() { exists(result) } } // Floating point conversions - class Conv_r4 extends Conversion, @cil_conv_r4 { - override string getOpcodeName() { result="conv.r4" } + override string getOpcodeName() { result = "conv.r4" } + override FloatType getType() { exists(result) } } class Conv_r8 extends Conversion, @cil_conv_r8 { - override string getOpcodeName() { result="conv.r8" } + override string getOpcodeName() { result = "conv.r8" } + override DoubleType getType() { exists(result) } } class Conv_r_un extends Conversion, @cil_conv_r_un { - override string getOpcodeName() { result="conv.r.un" } - override DoubleType getType() { exists(result) } // ?? + override string getOpcodeName() { result = "conv.r.un" } + + override DoubleType getType() { exists(result) } // ?? } class Volatile extends Instruction, @cil_volatile { - override string getOpcodeName() { result="volatile." } + override string getOpcodeName() { result = "volatile." } } // Indirections - class Ldind_i extends LoadIndirect, @cil_ldind_i { - override string getOpcodeName() { result="ldind.i" } + override string getOpcodeName() { result = "ldind.i" } + override IntType getType() { exists(result) } } class Ldind_i1 extends LoadIndirect, @cil_ldind_i1 { - override string getOpcodeName() { result="ldind.i1" } + override string getOpcodeName() { result = "ldind.i1" } + override SByteType getType() { exists(result) } } class Ldind_i2 extends LoadIndirect, @cil_ldind_i2 { - override string getOpcodeName() { result="ldind.i2" } + override string getOpcodeName() { result = "ldind.i2" } + override ShortType getType() { exists(result) } } class Ldind_i4 extends LoadIndirect, @cil_ldind_i4 { - override string getOpcodeName() { result="ldind.i4" } + override string getOpcodeName() { result = "ldind.i4" } + override IntType getType() { exists(result) } } class Ldind_i8 extends LoadIndirect, @cil_ldind_i8 { - override string getOpcodeName() { result="ldind.i8" } + override string getOpcodeName() { result = "ldind.i8" } + override LongType getType() { exists(result) } } class Ldind_r4 extends LoadIndirect, @cil_ldind_r4 { - override string getOpcodeName() { result="ldind.r4" } + override string getOpcodeName() { result = "ldind.r4" } + override FloatType getType() { exists(result) } } class Ldind_r8 extends LoadIndirect, @cil_ldind_r8 { - override string getOpcodeName() { result="ldind.r8" } + override string getOpcodeName() { result = "ldind.r8" } + override DoubleType getType() { exists(result) } } class Ldind_ref extends LoadIndirect, @cil_ldind_ref { - override string getOpcodeName() { result="ldind.ref" } + override string getOpcodeName() { result = "ldind.ref" } + override ObjectType getType() { exists(result) } } class Ldind_u1 extends LoadIndirect, @cil_ldind_u1 { - override string getOpcodeName() { result="ldind.u1" } + override string getOpcodeName() { result = "ldind.u1" } + override ByteType getType() { exists(result) } } class Ldind_u2 extends LoadIndirect, @cil_ldind_u2 { - override string getOpcodeName() { result="ldind.u2" } + override string getOpcodeName() { result = "ldind.u2" } + override UShortType getType() { exists(result) } } class Ldind_u4 extends LoadIndirect, @cil_ldind_u4 { - override string getOpcodeName() { result="ldind.u4" } + override string getOpcodeName() { result = "ldind.u4" } + override UIntType getType() { exists(result) } } class Stind_i extends StoreIndirect, @cil_stind_i { - override string getOpcodeName() { result="stind.i" } + override string getOpcodeName() { result = "stind.i" } } class Stind_i1 extends StoreIndirect, @cil_stind_i1 { - override string getOpcodeName() { result="stind.i1" } + override string getOpcodeName() { result = "stind.i1" } } class Stind_i2 extends StoreIndirect, @cil_stind_i2 { - override string getOpcodeName() { result="stind.i2" } + override string getOpcodeName() { result = "stind.i2" } } class Stind_i4 extends StoreIndirect, @cil_stind_i4 { - override string getOpcodeName() { result="stind.i4" } + override string getOpcodeName() { result = "stind.i4" } } class Stind_i8 extends StoreIndirect, @cil_stind_i8 { - override string getOpcodeName() { result="stind.i8" } + override string getOpcodeName() { result = "stind.i8" } } class Stind_r4 extends StoreIndirect, @cil_stind_r4 { - override string getOpcodeName() { result="stind.r4" } + override string getOpcodeName() { result = "stind.r4" } } class Stind_r8 extends StoreIndirect, @cil_stind_r8 { - override string getOpcodeName() { result="stind.r4" } + override string getOpcodeName() { result = "stind.r4" } } class Stind_ref extends StoreIndirect, @cil_stind_ref { - override string getOpcodeName() { result="stind.ref" } + override string getOpcodeName() { result = "stind.ref" } } // Miscellaneous - class Stobj extends Instruction, @cil_stobj { - override string getOpcodeName() { result="stobj"} - override int getPopCount() { result=2 } + override string getOpcodeName() { result = "stobj" } + + override int getPopCount() { result = 2 } } class Ldftn extends Expr, @cil_ldftn { - override string getOpcodeName() { result="ldftn" } - override int getPopCount() { result=0 } + override string getOpcodeName() { result = "ldftn" } + + override int getPopCount() { result = 0 } } class Ldvirtftn extends Expr, @cil_ldvirtftn { - override string getOpcodeName() { result="ldvirtftn" } - override int getPopCount() { result=1 } + override string getOpcodeName() { result = "ldvirtftn" } + + override int getPopCount() { result = 1 } } class Sizeof extends Expr, @cil_sizeof { - override string getOpcodeName() { result="sizeof" } + override string getOpcodeName() { result = "sizeof" } + override IntType getType() { exists(result) } } class Localloc extends Expr, @cil_localloc { - override string getOpcodeName() { result="localloc" } - override int getPopCount() { result=1 } // ?? + override string getOpcodeName() { result = "localloc" } + + override int getPopCount() { result = 1 } // ?? } class Readonly extends Instruction, @cil_readonly { - override string getOpcodeName() { result="readonly." } + override string getOpcodeName() { result = "readonly." } } class Mkrefany extends Expr, @cil_mkrefany { - override string getOpcodeName() { result="mkrefany" } - override int getPopCount() { result=1 } - override Type getType() { result=getAccess() } + override string getOpcodeName() { result = "mkrefany" } + + override int getPopCount() { result = 1 } + + override Type getType() { result = getAccess() } } class Refanytype extends Expr, @cil_refanytype { - override string getOpcodeName() { result="refanytype" } - override int getPopCount() { result=1 } + override string getOpcodeName() { result = "refanytype" } + + override int getPopCount() { result = 1 } + override SystemType getType() { exists(result) } } class Arglist extends Expr, @cil_arglist { - override string getOpcodeName() { result="arglist" } + override string getOpcodeName() { result = "arglist" } } } diff --git a/csharp/ql/src/semmle/code/cil/Method.qll b/csharp/ql/src/semmle/code/cil/Method.qll index 1cbc832b887..cc797abe7cc 100644 --- a/csharp/ql/src/semmle/code/cil/Method.qll +++ b/csharp/ql/src/semmle/code/cil/Method.qll @@ -13,53 +13,45 @@ private import dotnet * An implementation of a method in an assembly. */ class MethodImplementation extends EntryPoint, @cil_method_implementation { - /** Gets the method of this implementation. */ - Method getMethod() { cil_method_implementation(this,result,_) } + Method getMethod() { cil_method_implementation(this, result, _) } - override MethodImplementation getImplementation() { result=this } + override MethodImplementation getImplementation() { result = this } /** Gets the location of this implementation. */ - Assembly getLocation() { cil_method_implementation(this,_,result) } + Assembly getLocation() { cil_method_implementation(this, _, result) } /** Gets the instruction at index `index`. */ - Instruction getInstruction(int index) { - cil_instruction(result,_,index,this) - } + Instruction getInstruction(int index) { cil_instruction(result, _, index, this) } /** Gets the `n`th local variable of this implementation. */ LocalVariable getLocalVariable(int n) { cil_local_variable(result, this, n, _) } /** Gets a local variable of this implementation, if any. */ - LocalVariable getALocalVariable() { result=getLocalVariable(_) } + LocalVariable getALocalVariable() { result = getLocalVariable(_) } /** Gets an instruction in this implementation, if any. */ - Instruction getAnInstruction() { - result = getInstruction(_) - } + Instruction getAnInstruction() { result = getInstruction(_) } /** Gets the total number of instructions in this implementation. */ - int getNumberOfInstructions() { - result = count(getAnInstruction()) - } + int getNumberOfInstructions() { result = count(getAnInstruction()) } /** Gets the `i`th handler in this implementation. */ - Handler getHandler(int i) { - result.getImplementation()=this and result.getIndex()=i - } + Handler getHandler(int i) { result.getImplementation() = this and result.getIndex() = i } /** Gets a handler in this implementation, if any. */ - Handler getAHandler() { result.getImplementation()=this } + Handler getAHandler() { result.getImplementation() = this } - override Instruction getASuccessorType(FlowType t) { t instanceof NormalFlow and result.getImplementation()=this and result.getIndex()=0 } + override Instruction getASuccessorType(FlowType t) { + t instanceof NormalFlow and result.getImplementation() = this and result.getIndex() = 0 + } /** Gets the maximum stack size of this implementation. */ int getStackSize() { cil_method_stack_size(this, result) } - override string toString() { result=getMethod().toString() } + override string toString() { result = getMethod().toString() } } - /** * A method, which corresponds to any callable in C#, including constructors, * destructors, operators, accessors and so on. @@ -69,7 +61,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN * Gets a method implementation, if any. Note that there can * be several implementations in different assemblies. */ - MethodImplementation getAnImplementation() { result.getMethod()=this } + MethodImplementation getAnImplementation() { result.getMethod() = this } override Method getMethod() { result = this } @@ -92,12 +84,10 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) } override Parameter getParameter(int n) { - if isStatic() - then result=getRawParameter(n) - else (result=getRawParameter(n+1) and n>=0) - } + if isStatic() then result = getRawParameter(n) else (result = getRawParameter(n + 1) and n >= 0) + } - override Type getType() { result=getReturnType() } + override Type getType() { result = getReturnType() } /** Gets the return type of this method. */ override Type getReturnType() { cil_method(this, _, _, result) } @@ -106,15 +96,13 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN predicate returnsVoid() { getReturnType() instanceof VoidType } /** Gets the number of stack items pushed in a call to this method. */ - int getCallPushCount() { if returnsVoid() then result=0 else result=1 } + int getCallPushCount() { if returnsVoid() then result = 0 else result = 1 } /** Gets the number of stack items popped in a call to this method. */ - int getCallPopCount() { result=count(getRawParameter(_)) } + int getCallPopCount() { result = count(getRawParameter(_)) } /** Gets a method called by this method. */ - Method getACallee() { - result = getAnImplementation().getAnInstruction().(Call).getTarget() - } + Method getACallee() { result = getAnImplementation().getAnInstruction().(Call).getTarget() } /** Holds if this method is `virtual`. */ predicate isVirtual() { cil_virtual(this) } @@ -136,16 +124,16 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN override Method getSourceDeclaration() { result = getUnboundMethod() } /** Holds if this method is an instance constructor. */ - predicate isInstanceConstructor() { isSpecial() and getName()=".ctor" } + predicate isInstanceConstructor() { isSpecial() and getName() = ".ctor" } /** Holds if this method is a static class constructor. */ - predicate isStaticConstructor() { isSpecial() and getName()=".cctor" } + predicate isStaticConstructor() { isSpecial() and getName() = ".cctor" } /** Holds if this method is a constructor (static or instance). */ predicate isConstructor() { isStaticConstructor() or isInstanceConstructor() } /** Holds if this method is a destructor/finalizer. */ - predicate isFinalizer() { getOverriddenMethod*().getQualifiedName()="System.Object.Finalize" } + predicate isFinalizer() { getOverriddenMethod*().getQualifiedName() = "System.Object.Finalize" } /** Holds if this method is an operator. */ predicate isOperator() { isSpecial() and getName().matches("op\\_%") } @@ -163,10 +151,10 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN predicate isRemove() { isSpecial() and getName().matches("remove\\_%") } /** Holds if this method is an implicit conversion operator. */ - predicate isImplicitConversion() { isSpecial() and getName()="op_Implicit" } + predicate isImplicitConversion() { isSpecial() and getName() = "op_Implicit" } /** Holds if this method is an explicit conversion operator. */ - predicate isExplicitConversion() { isSpecial() and getName()="op_Explicit" } + predicate isExplicitConversion() { isSpecial() and getName() = "op_Explicit" } /** Holds if this method is a conversion operator. */ predicate isConversion() { isImplicitConversion() or isExplicitConversion() } @@ -175,14 +163,10 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN * Gets a method that is overridden, either in a base class * or in an interface. */ - Method getOverriddenMethod() { - cil_implements(this, result) - } + Method getOverriddenMethod() { cil_implements(this, result) } /** Gets a method that overrides this method, if any. */ - final Method getAnOverrider() { - result.getOverriddenMethod() = this - } + final Method getAnOverrider() { result.getOverriddenMethod() = this } override predicate hasBody() { exists(getAnImplementation()) } @@ -192,19 +176,13 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN } /** A destructor/finalizer. */ -class Destructor extends Method, DotNet::Destructor { - Destructor() { this.isFinalizer() } -} +class Destructor extends Method, DotNet::Destructor { Destructor() { this.isFinalizer() } } /** A constructor. */ -class Constructor extends Method, DotNet::Constructor { - Constructor() { this.isConstructor() } -} +class Constructor extends Method, DotNet::Constructor { Constructor() { this.isConstructor() } } /** A static/class constructor. */ -class StaticConstructor extends Constructor { - StaticConstructor() { this.isStaticConstructor() } -} +class StaticConstructor extends Constructor { StaticConstructor() { this.isStaticConstructor() } } /** An instance constructor. */ class InstanceConstructor extends Constructor { @@ -214,8 +192,7 @@ class InstanceConstructor extends Constructor { /** A method that always returns the `this` parameter. */ class ChainingMethod extends Method { ChainingMethod() { - forex(Return ret | - ret = getAnImplementation().getAnInstruction() | + forex(Return ret | ret = getAnImplementation().getAnInstruction() | ret.getExpr() instanceof ThisAccess ) } @@ -229,8 +206,9 @@ abstract class Accessor extends Method { /** A getter. */ class Getter extends Accessor { - Getter() { cil_getter(_,this) } - override Property getProperty() { cil_getter(result,this) } + Getter() { cil_getter(_, this) } + + override Property getProperty() { cil_getter(result, this) } } /** @@ -240,22 +218,23 @@ class Getter extends Accessor { class TrivialGetter extends Method { TrivialGetter() { exists(MethodImplementation impl | impl = getAnImplementation() | - impl.getInstruction(0) instanceof ThisAccess - and impl.getInstruction(1) instanceof FieldReadAccess - and impl.getInstruction(2) instanceof Return + impl.getInstruction(0) instanceof ThisAccess and + impl.getInstruction(1) instanceof FieldReadAccess and + impl.getInstruction(2) instanceof Return ) } /** Gets the underlying field of this getter. */ Field getField() { - getAnImplementation().getAnInstruction().(FieldReadAccess).getTarget()=result + getAnImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result } } /** A setter. */ class Setter extends Accessor { - Setter() { cil_setter(_,this) } - override Property getProperty() { cil_setter(result,this) } + Setter() { cil_setter(_, this) } + + override Property getProperty() { cil_setter(result, this) } } /** @@ -265,9 +244,9 @@ class Setter extends Accessor { class TrivialSetter extends Method { TrivialSetter() { exists(MethodImplementation impl | impl = getAnImplementation() | - impl.getInstruction(0) instanceof ThisAccess - and impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 - and impl.getInstruction(2) instanceof FieldWriteAccess + impl.getInstruction(0) instanceof ThisAccess and + impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 and + impl.getInstruction(2) instanceof FieldWriteAccess ) } @@ -285,5 +264,5 @@ class Operator extends Method { Operator() { this.isOperator() } /** Gets the name of the implementing method (for compatibility with C# data model). */ - string getFunctionName() { result=getName() } + string getFunctionName() { result = getName() } } diff --git a/csharp/ql/src/semmle/code/cil/Type.qll b/csharp/ql/src/semmle/code/cil/Type.qll index e0e64c4a9d1..98941b77ae9 100644 --- a/csharp/ql/src/semmle/code/cil/Type.qll +++ b/csharp/ql/src/semmle/code/cil/Type.qll @@ -19,10 +19,14 @@ class TypeContainer extends DotNet::NamedElement, @cil_type_container { /** A namespace. */ class Namespace extends DotNet::Namespace, TypeContainer, @namespace { - override string toString() { result=getQualifiedName() } + override string toString() { result = getQualifiedName() } + override Namespace getParent() { result = this.getParentNamespace() } + override Namespace getParentNamespace() { parent_namespace(this, result) } - override string getName() { namespaces(this,result) } + + override string getName() { namespaces(this, result) } + override Location getLocation() { none() } } @@ -31,14 +35,16 @@ class Namespace extends DotNet::Namespace, TypeContainer, @namespace { */ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { override TypeContainer getParent() { cil_type(this, _, _, result, _) } + override string getName() { cil_type(this, result, _, _, _) } + override string toString() { result = getQualifiedName() } /** Gets the containing type of this type, if any. */ override Type getDeclaringType() { result = getParent() } /** Gets a member of this type, if any. */ - Member getAMember() { result.getDeclaringType()=this } + Member getAMember() { result.getDeclaringType() = this } /** * Gets the unbound generic type of this type, or `this` if the type @@ -69,8 +75,7 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { * faster to compute. */ predicate isSystemType(string name) { - exists(Namespace system | - this.getParent() = system | + exists(Namespace system | this.getParent() = system | system.getName() = "System" and system.getParentNamespace() instanceof DotNet::GlobalNamespace and name = this.getName() @@ -87,10 +92,9 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { predicate isPrivate() { cil_private(this) } /** Gets the machine type used to store this type. */ - Type getUnderlyingType() { result=this } + Type getUnderlyingType() { result = this } // Class hierarchy - /** Gets the immediate base class of this class, if any. */ Type getBaseClass() { cil_base_class(this, result) } @@ -101,14 +105,14 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type { Type getABaseType() { result = getBaseClass() or result = getABaseInterface() } /** Gets an immediate subtype of this type, if any. */ - Type getASubtype() { result.getABaseType()=this } + Type getASubtype() { result.getABaseType() = this } /** Gets the namespace directly containing this type, if any. */ - Namespace getNamespace() { result=getParent() } + Namespace getNamespace() { result = getParent() } /** * Gets an index for implicit conversions. A type can be converted to another numeric type * of a higher index. */ - int getConversionIndex() { result=0 } + int getConversionIndex() { result = 0 } } diff --git a/csharp/ql/src/semmle/code/cil/Types.qll b/csharp/ql/src/semmle/code/cil/Types.qll index 63a9a223044..36f982846a9 100644 --- a/csharp/ql/src/semmle/code/cil/Types.qll +++ b/csharp/ql/src/semmle/code/cil/Types.qll @@ -11,7 +11,8 @@ class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter { /** Gets the generic type/method declaring this type parameter. */ TypeContainer getGeneric() { cil_type_parameter(result, _, this) } - override Location getLocation() { result=getParent().getLocation() } + + override Location getLocation() { result = getParent().getLocation() } /** Holds if this type parameter has the `new` constraint. */ predicate isDefaultConstructible() { cil_typeparam_new(this) } @@ -28,14 +29,17 @@ class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter { predicate isContravariant() { cil_typeparam_contravariant(this) } /** Gets a type constraint on this type parameter, if any. */ - Type getATypeConstraint() { cil_typeparam_constraint(this,result) } + Type getATypeConstraint() { cil_typeparam_constraint(this, result) } } /** A value or reference type. */ class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype { override ValueOrRefType getDeclaringType() { result = getParent() } + override string getUndecoratedName() { result = getName() } + override Namespace getDeclaringNamespace() { result = getNamespace() } + override ValueOrRefType getABaseType() { result = Type.super.getABaseType() } } @@ -48,31 +52,28 @@ class Enum extends ValueOrRefType { } /** A `class`. */ -class Class extends ValueOrRefType { - Class() { this.isClass() } -} +class Class extends ValueOrRefType { Class() { this.isClass() } } /** An `interface`. */ -class Interface extends ValueOrRefType { - Interface() { this.isInterface() } -} +class Interface extends ValueOrRefType { Interface() { this.isInterface() } } /** An array. */ class ArrayType extends DotNet::ArrayType, Type, @cil_array_type { - override Type getElementType() { cil_array_type(this,result,_) } + override Type getElementType() { cil_array_type(this, result, _) } /** Gets the rank of this array. */ - int getRank() { cil_array_type(this,_,result) } + int getRank() { cil_array_type(this, _, result) } override string toStringWithTypes() { result = DotNet::ArrayType.super.toStringWithTypes() } - override Location getLocation() { result=getElementType().getLocation() } + override Location getLocation() { result = getElementType().getLocation() } + override ValueOrRefType getABaseType() { result = Type.super.getABaseType() } } /** A pointer type. */ class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type { - override Type getReferentType() { cil_pointer_type(this,result) } + override Type getReferentType() { cil_pointer_type(this, result) } override IntType getUnderlyingType() { any() } @@ -86,164 +87,194 @@ class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type } /** A primitive type, built into the runtime. */ -abstract class PrimitiveType extends Type { -} +abstract class PrimitiveType extends Type { } /** * A primitive numeric type. * Either an integral type (`IntegralType`) or a floating point type (`FloatingPointType`). */ -abstract class NumericType extends PrimitiveType, ValueOrRefType { -} +abstract class NumericType extends PrimitiveType, ValueOrRefType { } /** A floating point type. Either single precision (`FloatType`) or double precision (`DoubleType`). */ -abstract class FloatingPointType extends NumericType { -} +abstract class FloatingPointType extends NumericType { } /** * An integral numeric type. Either a signed integral type (`SignedIntegralType`) * or an unsigned integral type (`UnsignedIntegralType`). */ -abstract class IntegralType extends NumericType { -} +abstract class IntegralType extends NumericType { } /** A signed integral type. */ -abstract class SignedIntegralType extends IntegralType { -} +abstract class SignedIntegralType extends IntegralType { } /** An unsigned integral type. */ -abstract class UnsignedIntegralType extends IntegralType { -} +abstract class UnsignedIntegralType extends IntegralType { } /** The `void` type, `System.Void`. */ class VoidType extends PrimitiveType { VoidType() { this.isSystemType("Void") } - override string toString() { result="void" } - override string toStringWithTypes() { result="void" } + + override string toString() { result = "void" } + + override string toStringWithTypes() { result = "void" } } /** The type `System.Int32`. */ class IntType extends SignedIntegralType { IntType() { this.isSystemType("Int32") } - override string toStringWithTypes() { result="int" } + + override string toStringWithTypes() { result = "int" } + override int getConversionIndex() { result = 8 } - override IntType getUnderlyingType() { result=this } + + override IntType getUnderlyingType() { result = this } } /** The type `System.IntPtr`. */ class IntPtrType extends PrimitiveType { IntPtrType() { this.isSystemType("IntPtr") } + override IntType getUnderlyingType() { any() } } /** The type `System.UIntPtr`. */ class UIntPtrType extends PrimitiveType { UIntPtrType() { this.isSystemType("UIntPtr") } + override IntType getUnderlyingType() { any() } } /** The type `System.UInt32`. */ class UIntType extends UnsignedIntegralType { UIntType() { this.isSystemType("UInt32") } - override string toStringWithTypes() { result="uint" } - override int getConversionIndex() { result=7 } + + override string toStringWithTypes() { result = "uint" } + + override int getConversionIndex() { result = 7 } + override IntType getUnderlyingType() { any() } } /** The type `System.SByte`. */ class SByteType extends SignedIntegralType { SByteType() { this.isSystemType("SByte") } - override string toStringWithTypes() { result="sbyte" } - override int getConversionIndex() { result=2 } + + override string toStringWithTypes() { result = "sbyte" } + + override int getConversionIndex() { result = 2 } } /** The type `System.Byte`. */ class ByteType extends UnsignedIntegralType { ByteType() { this.isSystemType("Byte") } - override string toStringWithTypes() { result="byte" } - override int getConversionIndex() { result=1 } + + override string toStringWithTypes() { result = "byte" } + + override int getConversionIndex() { result = 1 } + override SByteType getUnderlyingType() { any() } } /** The type `System.Int16`. */ class ShortType extends SignedIntegralType { ShortType() { this.isSystemType("Int16") } - override string toStringWithTypes() { result="short" } - override int getConversionIndex() { result=4 } + + override string toStringWithTypes() { result = "short" } + + override int getConversionIndex() { result = 4 } } /** The type `System.UInt16`. */ class UShortType extends UnsignedIntegralType { UShortType() { this.isSystemType("UInt16") } - override string toStringWithTypes() { result="ushort" } - override int getConversionIndex() { result=3 } + + override string toStringWithTypes() { result = "ushort" } + + override int getConversionIndex() { result = 3 } + override ShortType getUnderlyingType() { any() } } /** The type `System.Int64`. */ class LongType extends SignedIntegralType { LongType() { this.isSystemType("Int64") } - override string toStringWithTypes() { result="long" } - override int getConversionIndex() { result=10 } + + override string toStringWithTypes() { result = "long" } + + override int getConversionIndex() { result = 10 } } /** The type `System.UInt64`. */ class ULongType extends UnsignedIntegralType { ULongType() { this.isSystemType("UInt64") } - override string toStringWithTypes() { result="ulong" } - override int getConversionIndex() { result=9 } + + override string toStringWithTypes() { result = "ulong" } + + override int getConversionIndex() { result = 9 } + override LongType getUnderlyingType() { any() } } /** The type `System.Decimal`. */ class DecimalType extends SignedIntegralType { DecimalType() { this.isSystemType("Decimal") } - override string toStringWithTypes() { result="decimal" } - override int getConversionIndex() { result=13 } + + override string toStringWithTypes() { result = "decimal" } + + override int getConversionIndex() { result = 13 } } /** The type `System.String`. */ class StringType extends PrimitiveType, ValueOrRefType { StringType() { this.isSystemType("String") } - override string toStringWithTypes() { result="string" } + + override string toStringWithTypes() { result = "string" } } /** The type `System.Object`. */ class ObjectType extends ValueOrRefType { ObjectType() { this.isSystemType("Object") } - override string toStringWithTypes() { result="object" } + + override string toStringWithTypes() { result = "object" } } /** The type `System.Boolean`. */ class BoolType extends PrimitiveType, ValueOrRefType { BoolType() { this.isSystemType("Boolean") } - override string toStringWithTypes() { result="bool" } + + override string toStringWithTypes() { result = "bool" } + override IntType getUnderlyingType() { any() } } /** The type `System.Double`. */ class DoubleType extends FloatingPointType { DoubleType() { this.isSystemType("Double") } - override string toStringWithTypes() { result="double" } - override int getConversionIndex() { result=12 } + + override string toStringWithTypes() { result = "double" } + + override int getConversionIndex() { result = 12 } } /** The type `System.Single`. */ class FloatType extends FloatingPointType { FloatType() { this.isSystemType("Single") } - override string toStringWithTypes() { result="float" } - override int getConversionIndex() { result=4 } + + override string toStringWithTypes() { result = "float" } + + override int getConversionIndex() { result = 4 } } /** The type `System.Char`. */ class CharType extends IntegralType { CharType() { this.isSystemType("Char") } - override string toStringWithTypes() { result="char" } - override int getConversionIndex() { result=6 } + + override string toStringWithTypes() { result = "char" } + + override int getConversionIndex() { result = 6 } + override IntType getUnderlyingType() { any() } } /** The type `System.Type`. */ -class SystemType extends ValueOrRefType { - SystemType() { this.isSystemType("Type") } -} +class SystemType extends ValueOrRefType { SystemType() { this.isSystemType("Type") } } diff --git a/csharp/ql/src/semmle/code/cil/Variable.qll b/csharp/ql/src/semmle/code/cil/Variable.qll index 5462cc6f541..83a4bda7063 100644 --- a/csharp/ql/src/semmle/code/cil/Variable.qll +++ b/csharp/ql/src/semmle/code/cil/Variable.qll @@ -14,13 +14,13 @@ class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variabl override string toStringWithTypes() { none() } /** Gets an access to this variable, if any. */ - VariableAccess getAnAccess() { result.getTarget()=this } + VariableAccess getAnAccess() { result.getTarget() = this } /** Gets a read access to this variable, if any. */ - ReadAccess getARead() { result=getAnAccess() } + ReadAccess getARead() { result = getAnAccess() } /** Gets a write access to this variable, if any. */ - WriteAccess getAWrite() { result=getAnAccess() } + WriteAccess getAWrite() { result = getAnAccess() } override string toString() { result = Declaration.super.toString() } @@ -28,8 +28,7 @@ class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variabl } /** A stack variable. Either a local variable (`LocalVariable`) or a parameter (`Parameter`). */ -class StackVariable extends Variable, @cil_stack_variable { -} +class StackVariable extends Variable, @cil_stack_variable { } /** * A local variable. @@ -37,33 +36,35 @@ class StackVariable extends Variable, @cil_stack_variable { * Each method in CIL has a number of typed local variables, in addition to the evaluation stack. */ class LocalVariable extends StackVariable, @cil_local_variable { - override string toString() { result="Local variable " + getIndex() + " of method " + getImplementation().getMethod() } + override string toString() { + result = "Local variable " + getIndex() + " of method " + getImplementation().getMethod() + } /** Gets the method implementation defining this local variable. */ - MethodImplementation getImplementation() { this=result.getALocalVariable() } + MethodImplementation getImplementation() { this = result.getALocalVariable() } /** Gets the index number of this local variable. This is not usually significant. */ int getIndex() { this = getImplementation().getLocalVariable(result) } override Type getType() { cil_local_variable(this, _, _, result) } - override Location getLocation() { result=getImplementation().getLocation() } + override Location getLocation() { result = getImplementation().getLocation() } - override Method getMethod() { result=getImplementation().getMethod() } + override Method getMethod() { result = getImplementation().getMethod() } } /** A method parameter. */ class Parameter extends DotNet::Parameter, StackVariable, @cil_parameter { - /** Gets the method declaring this parameter. */ - override Method getMethod() { this=result.getARawParameter() } + override Method getMethod() { this = result.getARawParameter() } - override Method getCallable() { result=getMethod() } + override Method getCallable() { result = getMethod() } /** Gets the index of this parameter. */ int getIndex() { cil_parameter(this, _, result, _) } - override string toString() { result="Parameter " + getIndex() + " of " + getMethod() } + override string toString() { result = "Parameter " + getIndex() + " of " + getMethod() } + override Type getType() { cil_parameter(this, _, _, result) } /** @@ -86,9 +87,11 @@ class Parameter extends DotNet::Parameter, StackVariable, @cil_parameter { override string toStringWithTypes() { result = getPrefix() + getType().toStringWithTypes() } - private string getPrefix() { if isOut() then result="out " else if isRef() then result="ref " else result="" } + private string getPrefix() { + if isOut() then result = "out " else if isRef() then result = "ref " else result = "" + } - override Location getLocation() { result=getMethod().getLocation() } + override Location getLocation() { result = getMethod().getLocation() } override ParameterAccess getAnAccess() { result.getTarget() = this } @@ -105,17 +108,24 @@ class Parameter extends DotNet::Parameter, StackVariable, @cil_parameter { /** A parameter corresponding to `this`. */ class ThisParameter extends Parameter { ThisParameter() { - not this.getMethod().isStatic() - and this.getIndex()=0 + not this.getMethod().isStatic() and + this.getIndex() = 0 } } /** A field. */ class Field extends DotNet::Field, Variable, Member, @cil_field { - override string toString() { result=getName() } - override string toStringWithTypes() { result=getDeclaringType().toStringWithTypes() + "." + getName() } - override string getName() { cil_field(this,_,result,_) } + override string toString() { result = getName() } + + override string toStringWithTypes() { + result = getDeclaringType().toStringWithTypes() + "." + getName() + } + + override string getName() { cil_field(this, _, result, _) } + override Type getType() { cil_field(this, _, _, result) } + override ValueOrRefType getDeclaringType() { cil_field(this, result, _, _) } - override Location getLocation() { result=getDeclaringType().getLocation() } + + override Location getLocation() { result = getDeclaringType().getLocation() } } diff --git a/csharp/ql/src/semmle/code/csharp/Assignable.qll b/csharp/ql/src/semmle/code/csharp/Assignable.qll index ee554964fff..96022dd22b1 100644 --- a/csharp/ql/src/semmle/code/csharp/Assignable.qll +++ b/csharp/ql/src/semmle/code/csharp/Assignable.qll @@ -27,9 +27,7 @@ class Assignable extends Declaration, @assignable { * property (`Property`), an indexer (`Indexer`), or an event (`Event`). */ class AssignableMember extends Member, Assignable { - override AssignableMemberAccess getAnAccess() { - result = Assignable.super.getAnAccess() - } + override AssignableMemberAccess getAnAccess() { result = Assignable.super.getAnAccess() } } /** @@ -38,9 +36,7 @@ class AssignableMember extends Member, Assignable { * (`IndexerAccess`), or an event access (`EventAccess`). */ class AssignableMemberAccess extends MemberAccess, AssignableAccess { - override AssignableMember getTarget() { - result = AssignableAccess.super.getTarget() - } + override AssignableMember getTarget() { result = AssignableAccess.super.getTarget() } } /** @@ -70,8 +66,7 @@ class AssignableRead extends AssignableAccess { this.isRefArgument() or this = any(AssignableDefinitions::AddressOfDefinition def).getTargetAccess() - ) - and + ) and not this = any(NameOfExpr noe).getAChildExpr*() } @@ -100,8 +95,7 @@ class AssignableRead extends AssignableAccess { * - The read of `this.Field` on line 11 is next to the read on line 10. */ AssignableRead getANextRead() { - forex(ControlFlow::Node cfn | - cfn = result.getAControlFlowNode() | + forex(ControlFlow::Node cfn | cfn = result.getAControlFlowNode() | Ssa::Internal::adjacentReadPairSameVar(this.getAControlFlowNode(), cfn) ) } @@ -113,9 +107,7 @@ class AssignableRead extends AssignableAccess { * * This is the transitive closure of `getANextRead()`. */ - AssignableRead getAReachableRead() { - result = this.getANextRead+() - } + AssignableRead getAReachableRead() { result = this.getANextRead+() } } /** @@ -136,11 +128,7 @@ class AssignableRead extends AssignableAccess { * ``` */ class AssignableWrite extends AssignableAccess { - AssignableWrite() { - exists(AssignableDefinition def | - def.getTargetAccess() = this - ) - } + AssignableWrite() { exists(AssignableDefinition def | def.getTargetAccess() = this) } } /** INTERNAL: Do not use. */ @@ -164,8 +152,7 @@ module AssignableInternal { left = ae.getLValue() and right = ae.getRValue() or - exists(TupleExpr l, TupleExpr r, int i | - tupleAssignmentPair(ae, l, r) | + exists(TupleExpr l, TupleExpr r, int i | tupleAssignmentPair(ae, l, r) | left = l.getArgument(i) and right = r.getArgument(i) ) @@ -196,12 +183,10 @@ module AssignableInternal { * recursion error). */ private Expr getArgumentForParameter(Call c, Parameter p) { - exists(Callable callable | - p = callable.getAParameter() | + exists(Callable callable | p = callable.getAParameter() | callable = c.(MethodCall).getTarget() or callable = c.(ObjectCreation).getTarget() - ) - and + ) and ( // Appears in the positional part of the call result = c.getArgument(p.getPosition()) and @@ -212,7 +197,8 @@ module AssignableInternal { ) } - pragma [noinline] // predicate folding to get proper join-order + // predicate folding to get proper join-order + pragma[noinline] private Expr getExplicitArgument(Call c, string name) { result = c.getAnArgument() and result.getExplicitArgumentName() = name @@ -223,8 +209,7 @@ module AssignableInternal { * the target callable is non-overridable and from source. */ private predicate isAnalyzableRefCall(Call c, AssignableAccess aa, Parameter p) { - exists(Callable callable | - callable = getRefCallTarget(c, aa, p) | + exists(Callable callable | callable = getRefCallTarget(c, aa, p) | not callable.(Virtualizable).isOverridableOrImplementable() and callable.hasBody() ) @@ -236,8 +221,7 @@ module AssignableInternal { * recursion. */ private predicate isNonAnalyzableRefCall(Call c, AssignableAccess aa, Parameter p) { - exists(Callable callable | - callable = getRefCallTarget(c, aa, p) | + exists(Callable callable | callable = getRefCallTarget(c, aa, p) | callable.(Virtualizable).isOverridableOrImplementable() or not callable.hasBody() ) @@ -259,14 +243,12 @@ module AssignableInternal { * any assignments to `p`. */ private predicate parameterReachesWithoutDef(Parameter p, ControlFlow::BasicBlock bb) { - not basicBlockRefParamDef(bb, p) - and + not basicBlockRefParamDef(bb, p) and ( isAnalyzableRefCall(_, _, p) and p.getCallable().getEntryPoint() = bb.getFirstNode() or - exists(ControlFlow::BasicBlock mid | - parameterReachesWithoutDef(p, mid) | + exists(ControlFlow::BasicBlock mid | parameterReachesWithoutDef(p, mid) | bb = mid.getASuccessor() ) ) @@ -277,45 +259,33 @@ module AssignableInternal { bb.getANode() = getAnAnalyzableRefDef(_, _, p).getAControlFlowNode() } - private cached module Cached { - cached newtype TAssignableDefinition = - TAssignmentDefinition(Assignment a) { - not a.getLValue() instanceof TupleExpr - } - or - TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { - tupleAssignmentDefinition(ae, leaf) - } - or + cached + private module Cached { + cached + newtype TAssignableDefinition = + TAssignmentDefinition(Assignment a) { not a.getLValue() instanceof TupleExpr } or + TTupleAssignmentDefinition(AssignExpr ae, Expr leaf) { tupleAssignmentDefinition(ae, leaf) } or TOutRefDefinition(AssignableAccess aa) { aa.isOutArgument() or isRelevantRefCall(_, aa) - } - or - TMutationDefinition(MutatorOperation mo) - or + } or + TMutationDefinition(MutatorOperation mo) or TLocalVariableDefinition(LocalVariableDeclExpr lvde) { not lvde.hasInitializer() and not exists(getTupleSource(TTupleAssignmentDefinition(_, lvde))) and not lvde = any(IsPatternExpr ipe).getVariableDeclExpr() and not lvde = any(TypeCase tc).getVariableDeclExpr() - } - or + } or TImplicitParameterDefinition(Parameter p) { - exists(Callable c | - p = c.getAParameter() | + exists(Callable c | p = c.getAParameter() | c.hasBody() or c.(Constructor).hasInitializer() ) - } - or - TAddressOfDefinition(AddressOfExpr aoe) - or - TIsPatternDefinition(IsPatternExpr ipe) - or - TTypeCasePatternDefinition(TypeCase tc) - or + } or + TAddressOfDefinition(AddressOfExpr aoe) or + TIsPatternDefinition(IsPatternExpr ipe) or + TTypeCasePatternDefinition(TypeCase tc) or TInitializer(Assignable a, Expr e) { e = a.(Field).getInitializer() or e = a.(Property).getInitializer() @@ -324,9 +294,9 @@ module AssignableInternal { /** * Gets the source expression assigned in tuple definition `def`, if any. */ - cached Expr getTupleSource(TTupleAssignmentDefinition def) { - exists(AssignExpr ae, Expr leaf | - def = TTupleAssignmentDefinition(ae, leaf) | + cached + Expr getTupleSource(TTupleAssignmentDefinition def) { + exists(AssignExpr ae, Expr leaf | def = TTupleAssignmentDefinition(ae, leaf) | tupleAssignmentPair(ae, leaf, result) ) } @@ -334,48 +304,44 @@ module AssignableInternal { /** * Holds if the `ref` assignment to `aa` via call `c` is uncertain. */ - cached predicate isUncertainRefCall(Call c, AssignableAccess aa) { - isRelevantRefCall(c, aa) - and - exists(ControlFlow::BasicBlock bb, Parameter p | - isAnalyzableRefCall(c, aa, p) | + cached + predicate isUncertainRefCall(Call c, AssignableAccess aa) { + isRelevantRefCall(c, aa) and + exists(ControlFlow::BasicBlock bb, Parameter p | isAnalyzableRefCall(c, aa, p) | parameterReachesWithoutDef(p, bb) and bb.getLastNode() = p.getCallable().getExitPoint() ) } // Not defined by dispatch in order to avoid too conservative negative recursion error - cached Assignable getTarget(AssignableDefinition def) { + cached + Assignable getTarget(AssignableDefinition def) { result = def.getTargetAccess().getTarget() or - exists(Expr leaf | - def = TTupleAssignmentDefinition(_, leaf) | + exists(Expr leaf | def = TTupleAssignmentDefinition(_, leaf) | result = leaf.(LocalVariableDeclExpr).getVariable() ) or - def = any(AssignableDefinitions::ImplicitParameterDefinition p | - result = p.getParameter() - ) + def = any(AssignableDefinitions::ImplicitParameterDefinition p | result = p.getParameter()) or def = any(AssignableDefinitions::LocalVariableDefinition decl | - result = decl.getDeclaration().getVariable() - ) + result = decl.getDeclaration().getVariable() + ) or def = any(AssignableDefinitions::IsPatternDefinition is | - result = is.getDeclaration().getVariable() - ) + result = is.getDeclaration().getVariable() + ) or def = any(AssignableDefinitions::TypeCasePatternDefinition case | - result = case.getDeclaration().getVariable() - ) + result = case.getDeclaration().getVariable() + ) or - def = any(AssignableDefinitions::InitializerDefinition init | - result = init.getAssignable() - ) + def = any(AssignableDefinitions::InitializerDefinition init | result = init.getAssignable()) } // Not defined by dispatch in order to avoid too conservative negative recursion error - cached AssignableAccess getTargetAccess(AssignableDefinition def) { + cached + AssignableAccess getTargetAccess(AssignableDefinition def) { def = TAssignmentDefinition(any(Assignment a | a.getLValue() = result)) or def = TTupleAssignmentDefinition(_, result) @@ -391,14 +357,13 @@ module AssignableInternal { * Gets the argument for the implicit `value` parameter in the accessor call * `ac`, if any. */ - cached Expr getAccessorCallValueArgument(AccessorCall ac) { - exists(AssignExpr ae | - tupleAssignmentDefinition(ae, ac) | + cached + Expr getAccessorCallValueArgument(AccessorCall ac) { + exists(AssignExpr ae | tupleAssignmentDefinition(ae, ac) | tupleAssignmentPair(ae, ac, result) ) or - exists(Assignment a | - ac = a.getLValue() | + exists(Assignment a | ac = a.getLValue() | result = a.getRValue() and not a.(AssignOperation).hasExpandedAssignment() ) @@ -406,7 +371,6 @@ module AssignableInternal { } import Cached } - private import AssignableInternal /** @@ -431,9 +395,7 @@ class AssignableDefinition extends TAssignableDefinition { * the definitions of `x` and `y` in `M(out x, out y)` and `(x, y) = (0, 1)` * relate to the same call to `M` and assignment node, respectively. */ - ControlFlow::Node getAControlFlowNode() { - result = this.getExpr().getAControlFlowNode() - } + ControlFlow::Node getAControlFlowNode() { result = this.getExpr().getAControlFlowNode() } /** * Gets the underlying expression that updates the targeted assignable when @@ -505,10 +467,8 @@ class AssignableDefinition extends TAssignableDefinition { * `AssignableRead.getANextRead()`. */ AssignableRead getAFirstRead() { - forex(ControlFlow::Node cfn | - cfn = result.getAControlFlowNode() | - exists(Ssa::ExplicitDefinition def | - result = def.getAFirstReadAtNode(cfn) | + forex(ControlFlow::Node cfn | cfn = result.getAControlFlowNode() | + exists(Ssa::ExplicitDefinition def | result = def.getAFirstReadAtNode(cfn) | this = def.getADefinition() ) ) @@ -521,17 +481,13 @@ class AssignableDefinition extends TAssignableDefinition { * * This is the equivalent with `getAFirstRead().getANextRead*()`. */ - AssignableRead getAReachableRead() { - result = this.getAFirstRead().getANextRead*() - } + AssignableRead getAReachableRead() { result = this.getAFirstRead().getANextRead*() } /** Gets a textual representation of this assignable definition. */ string toString() { none() } /** Gets the location of this assignable definition. */ - Location getLocation() { - result = this.getExpr().getLocation() - } + Location getLocation() { result = this.getExpr().getLocation() } } /** Provides different types of `AssignableDefinition`s. */ @@ -542,14 +498,10 @@ module AssignableDefinitions { class AssignmentDefinition extends AssignableDefinition, TAssignmentDefinition { Assignment a; - AssignmentDefinition() { - this = TAssignmentDefinition(a) - } + AssignmentDefinition() { this = TAssignmentDefinition(a) } /** Gets the underlying assignment. */ - Assignment getAssignment() { - result = a - } + Assignment getAssignment() { result = a } override Expr getExpr() { result = a } @@ -558,9 +510,7 @@ module AssignableDefinitions { not a instanceof AssignOperation } - override string toString() { - result = a.toString() - } + override string toString() { result = a.toString() } } /** @@ -569,16 +519,13 @@ module AssignableDefinitions { */ class TupleAssignmentDefinition extends AssignableDefinition, TTupleAssignmentDefinition { AssignExpr ae; + Expr leaf; - TupleAssignmentDefinition() { - this = TTupleAssignmentDefinition(ae, leaf) - } + TupleAssignmentDefinition() { this = TTupleAssignmentDefinition(ae, leaf) } /** Gets the underlying assignment. */ - AssignExpr getAssignment() { - result = ae - } + AssignExpr getAssignment() { result = ae } /** * Gets the evaluation order of this definition among the other definitions @@ -587,9 +534,12 @@ module AssignableDefinitions { */ int getEvaluationOrder() { leaf = rank[result + 1](Expr leaf0 | - exists(TTupleAssignmentDefinition(ae, leaf0)) | - leaf0 order by leaf0.getLocation().getStartLine(), leaf0.getLocation().getStartColumn() - ) + exists(TTupleAssignmentDefinition(ae, leaf0)) + | + leaf0 + order by + leaf0.getLocation().getStartLine(), leaf0.getLocation().getStartColumn() + ) } override Expr getExpr() { result = ae } @@ -598,9 +548,7 @@ module AssignableDefinitions { result = getTupleSource(this) // need not exist } - override string toString() { - result = ae.toString() - } + override string toString() { result = ae.toString() } } /** @@ -610,14 +558,10 @@ module AssignableDefinitions { class OutRefDefinition extends AssignableDefinition, TOutRefDefinition { AssignableAccess aa; - OutRefDefinition() { - this = TOutRefDefinition(aa) - } + OutRefDefinition() { this = TOutRefDefinition(aa) } /** Gets the underlying call. */ - Call getCall() { - result.getAnArgument() = aa - } + Call getCall() { result.getAnArgument() = aa } /** * Gets the index of this definition among the other definitions in the @@ -625,14 +569,13 @@ module AssignableDefinitions { * the definitions of `x` and `y` are 0 and 1, respectively. */ int getIndex() { - exists(ControlFlow::BasicBlock bb, int i | - bb.getNode(i).getElement() = aa | + exists(ControlFlow::BasicBlock bb, int i | bb.getNode(i).getElement() = aa | i = rank[result + 1](int j, OutRefDefinition def | - bb.getNode(j).getElement() = def.getTargetAccess() and - this.getCall() = def.getCall() + bb.getNode(j).getElement() = def.getTargetAccess() and + this.getCall() = def.getCall() | - j - ) + j + ) ) } @@ -642,13 +585,9 @@ module AssignableDefinitions { not isUncertainRefCall(this.getCall(), this.getTargetAccess()) } - override string toString() { - result = aa.toString() - } + override string toString() { result = aa.toString() } - override Location getLocation() { - result = aa.getLocation() - } + override Location getLocation() { result = aa.getLocation() } } /** @@ -657,20 +596,14 @@ module AssignableDefinitions { class MutationDefinition extends AssignableDefinition, TMutationDefinition { MutatorOperation mo; - MutationDefinition() { - this = TMutationDefinition(mo) - } + MutationDefinition() { this = TMutationDefinition(mo) } /** Gets the underlying mutator operation. */ - MutatorOperation getMutatorOperation() { - result = mo - } + MutatorOperation getMutatorOperation() { result = mo } override Expr getExpr() { result = mo } - override string toString() { - result = mo.toString() - } + override string toString() { result = mo.toString() } } /** @@ -679,20 +612,14 @@ module AssignableDefinitions { class LocalVariableDefinition extends AssignableDefinition, TLocalVariableDefinition { LocalVariableDeclExpr lvde; - LocalVariableDefinition() { - this = TLocalVariableDefinition(lvde) - } + LocalVariableDefinition() { this = TLocalVariableDefinition(lvde) } /** Gets the underlying local variable declaration. */ - LocalVariableDeclExpr getDeclaration() { - result = lvde - } + LocalVariableDeclExpr getDeclaration() { result = lvde } override Expr getExpr() { result = lvde } - override string toString() { - result = lvde.toString() - } + override string toString() { result = lvde.toString() } } /** @@ -702,32 +629,20 @@ module AssignableDefinitions { class ImplicitParameterDefinition extends AssignableDefinition, TImplicitParameterDefinition { Parameter p; - ImplicitParameterDefinition() { - this = TImplicitParameterDefinition(p) - } + ImplicitParameterDefinition() { this = TImplicitParameterDefinition(p) } /** Gets the underlying parameter. */ - Parameter getParameter() { - result = p - } + Parameter getParameter() { result = p } - override ControlFlow::Node getAControlFlowNode() { - result = p.getCallable().getEntryPoint() - } + override ControlFlow::Node getAControlFlowNode() { result = p.getCallable().getEntryPoint() } override Parameter getElement() { result = p } - override Callable getEnclosingCallable() { - result = p.getCallable() - } + override Callable getEnclosingCallable() { result = p.getCallable() } - override string toString() { - result = p.toString() - } + override string toString() { result = p.toString() } - override Location getLocation() { - result = this.getTarget().getLocation() - } + override Location getLocation() { result = this.getTarget().getLocation() } } /** @@ -736,20 +651,14 @@ module AssignableDefinitions { class AddressOfDefinition extends AssignableDefinition, TAddressOfDefinition { AddressOfExpr aoe; - AddressOfDefinition() { - this = TAddressOfDefinition(aoe) - } + AddressOfDefinition() { this = TAddressOfDefinition(aoe) } /** Gets the underlying address-of expression. */ - AddressOfExpr getAddressOf() { - result = aoe - } + AddressOfExpr getAddressOf() { result = aoe } override Expr getExpr() { result = aoe } - override string toString() { - result = aoe.toString() - } + override string toString() { result = aoe.toString() } } /** @@ -758,24 +667,16 @@ module AssignableDefinitions { class IsPatternDefinition extends AssignableDefinition, TIsPatternDefinition { IsPatternExpr ipe; - IsPatternDefinition() { - this = TIsPatternDefinition(ipe) - } + IsPatternDefinition() { this = TIsPatternDefinition(ipe) } /** Gets the underlying local variable declaration. */ - LocalVariableDeclExpr getDeclaration() { - result = ipe.getVariableDeclExpr() - } + LocalVariableDeclExpr getDeclaration() { result = ipe.getVariableDeclExpr() } override Expr getExpr() { result = this.getDeclaration() } - override Expr getSource() { - result = ipe.getExpr() - } + override Expr getSource() { result = ipe.getExpr() } - override string toString() { - result = this.getDeclaration().toString() - } + override string toString() { result = this.getDeclaration().toString() } } /** @@ -793,14 +694,10 @@ module AssignableDefinitions { class TypeCasePatternDefinition extends AssignableDefinition, TTypeCasePatternDefinition { TypeCase tc; - TypeCasePatternDefinition() { - this = TTypeCasePatternDefinition(tc) - } + TypeCasePatternDefinition() { this = TTypeCasePatternDefinition(tc) } /** Gets the underlying local variable declaration. */ - LocalVariableDeclExpr getDeclaration() { - result = tc.getVariableDeclExpr() - } + LocalVariableDeclExpr getDeclaration() { result = tc.getVariableDeclExpr() } override Expr getExpr() { result = this.getDeclaration() } @@ -808,9 +705,7 @@ module AssignableDefinitions { result = any(SwitchStmt ss | ss.getATypeCase() = tc).getCondition() } - override string toString() { - result = this.getDeclaration().toString() - } + override string toString() { result = this.getDeclaration().toString() } } /** @@ -825,27 +720,18 @@ module AssignableDefinitions { */ class InitializerDefinition extends AssignableDefinition, TInitializer { Assignable a; + Expr e; - InitializerDefinition() { - this = TInitializer(a, e) - } + InitializerDefinition() { this = TInitializer(a, e) } /** Gets the assignable (field or property) being initialized. */ - Assignable getAssignable() { - result = a - } + Assignable getAssignable() { result = a } - override Expr getSource() { - result = e - } + override Expr getSource() { result = e } - override string toString() { - result = e.toString() - } + override string toString() { result = e.toString() } - override Location getLocation() { - result = e.getLocation() - } + override Location getLocation() { result = e.getLocation() } } } diff --git a/csharp/ql/src/semmle/code/csharp/Attribute.qll b/csharp/ql/src/semmle/code/csharp/Attribute.qll index 1e3de40681c..39458fc69a8 100644 --- a/csharp/ql/src/semmle/code/csharp/Attribute.qll +++ b/csharp/ql/src/semmle/code/csharp/Attribute.qll @@ -11,8 +11,7 @@ private import semmle.code.csharp.ExprOrStmtParent * a destructor (`Destructor`), a callable accessor (`CallableAccessor`), a value or reference type * (`ValueOrRefType`), or a declaration with accessors (`DeclarationWithAccessors`). */ -class Attributable extends @attributable -{ +class Attributable extends @attributable { /** Gets an attribute attached to this element, if any. */ final Attribute getAnAttribute() { result.getTarget() = this } @@ -36,7 +35,6 @@ class Attributable extends @attributable * ``` */ class Attribute extends TopLevelExprParent, @attribute { - /** Gets the type of this attribute. */ Class getType() { attributes(this, getTypeRef(result), _) } @@ -49,13 +47,8 @@ class Attribute extends TopLevelExprParent, @attribute { override Location getALocation() { attribute_location(this, result) } override string toString() { - exists(string type, string name | - type = getType().toString() | - if type.matches("%Attribute") then - name = type.prefix(type.length() - 9) - else - name = type - and + exists(string type, string name | type = getType().toString() | + (if type.matches("%Attribute") then name = type.prefix(type.length() - 9) else name = type) and result = "[" + name + "(...)]" ) } diff --git a/csharp/ql/src/semmle/code/csharp/Callable.qll b/csharp/ql/src/semmle/code/csharp/Callable.qll index 29d7c843565..3837346b565 100644 --- a/csharp/ql/src/semmle/code/csharp/Callable.qll +++ b/csharp/ql/src/semmle/code/csharp/Callable.qll @@ -28,9 +28,7 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal /** Holds if this callable returns a `ref readonly`. */ predicate returnsRefReadonly() { ref_readonly_returns(this) } - override Callable getSourceDeclaration() { - result = Parameterizable.super.getSourceDeclaration() - } + override Callable getSourceDeclaration() { result = Parameterizable.super.getSourceDeclaration() } /** * Gets the body of this callable, if any. @@ -88,9 +86,7 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal } /** Gets the statement body of this callable, if any. */ - final BlockStmt getStatementBody() { - result = this.getAChildStmt() - } + final BlockStmt getStatementBody() { result = this.getAChildStmt() } /** * Gets a statement body of this callable, if any. @@ -120,17 +116,13 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal * to the same assembly, then both `{ return 0; }` and `{ return 1; }` are * statement bodies of `N.C.M()`. */ - final BlockStmt getAStatementBody() { - stmt_parent_top_level(result, _, this) - } + final BlockStmt getAStatementBody() { stmt_parent_top_level(result, _, this) } /** Holds if this callable has a statement body. */ final predicate hasStatementBody() { exists(getStatementBody()) } /** Gets the expression body of this callable (if any), specified by `=>`. */ - final Expr getExpressionBody() { - result = this.getChildExpr(0) - } + final Expr getExpressionBody() { result = this.getChildExpr(0) } /** * Gets an expression body of this callable (if any), specified by `=>`. @@ -159,22 +151,16 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal * * to the same assembly, then both `0` and `1` are expression bodies of `N.C.M()`. */ - final Expr getAnExpressionBody() { - expr_parent_top_level_adjusted(result, 0, this) - } + final Expr getAnExpressionBody() { expr_parent_top_level_adjusted(result, 0, this) } /** Holds if this callable has an expression body. */ final predicate hasExpressionBody() { exists(getExpressionBody()) } /** Gets the entry point in the control graph for this callable. */ - ControlFlow::Nodes::EntryNode getEntryPoint() { - result.getCallable() = this - } + ControlFlow::Nodes::EntryNode getEntryPoint() { result.getCallable() = this } /** Gets the exit point in the control graph for this callable. */ - ControlFlow::Nodes::ExitNode getExitPoint() { - result.getCallable() = this - } + ControlFlow::Nodes::ExitNode getExitPoint() { result.getCallable() = this } /** * Gets the enclosing callable of this callable, if any. @@ -214,40 +200,26 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal } override predicate canReturn(DotNet::Expr e) { - exists(ReturnStmt ret | - ret.getEnclosingCallable() = this | - e = ret.getExpr() - ) + exists(ReturnStmt ret | ret.getEnclosingCallable() = this | e = ret.getExpr()) or e = getExpressionBody() } /** Holds if this callable can yield return the expression `e`. */ predicate canYieldReturn(Expr e) { - exists(YieldReturnStmt yield | - yield.getEnclosingCallable() = this | - e = yield.getExpr() - ) + exists(YieldReturnStmt yield | yield.getEnclosingCallable() = this | e = yield.getExpr()) } - override string toStringWithTypes() { - result = getName() + "(" + parameterTypesToString() + ")" - } + override string toStringWithTypes() { result = getName() + "(" + parameterTypesToString() + ")" } /** Gets a `Call` that has this callable as a target. */ Call getACall() { this = result.getTarget() } - override Parameter getParameter(int n) { - result = Parameterizable.super.getParameter(n) - } + override Parameter getParameter(int n) { result = Parameterizable.super.getParameter(n) } - override Parameter getAParameter() { - result = Parameterizable.super.getAParameter() - } + override Parameter getAParameter() { result = Parameterizable.super.getAParameter() } - override int getNumberOfParameters() { - result = Parameterizable.super.getNumberOfParameters() - } + override int getNumberOfParameters() { result = Parameterizable.super.getNumberOfParameters() } } /** @@ -260,31 +232,22 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal * ``` */ class Method extends Callable, Virtualizable, Attributable, @method { - /** Gets the name of this method. */ - override string getName() { methods(this,result,_,_,_) } + override string getName() { methods(this, result, _, _, _) } - override ValueOrRefType getDeclaringType() { methods(this,_,result,_,_) } + override ValueOrRefType getDeclaringType() { methods(this, _, result, _, _) } - override Type getReturnType() { methods(this,_,_,getTypeRef(result),_) } + override Type getReturnType() { methods(this, _, _, getTypeRef(result), _) } - override Method getSourceDeclaration() { methods(this,_,_,_,result) } + override Method getSourceDeclaration() { methods(this, _, _, _, result) } - override Method getOverridee() { - result = Virtualizable.super.getOverridee() - } + override Method getOverridee() { result = Virtualizable.super.getOverridee() } - override Method getAnOverrider() { - result = Virtualizable.super.getAnOverrider() - } + override Method getAnOverrider() { result = Virtualizable.super.getAnOverrider() } - override Method getImplementee() { - result = Virtualizable.super.getImplementee() - } + override Method getImplementee() { result = Virtualizable.super.getImplementee() } - override Method getAnImplementor() { - result = Virtualizable.super.getAnImplementor() - } + override Method getAnImplementor() { result = Virtualizable.super.getAnImplementor() } override Method getAnUltimateImplementee() { result = Virtualizable.super.getAnUltimateImplementee() @@ -297,14 +260,11 @@ class Method extends Callable, Virtualizable, Attributable, @method { override Location getALocation() { method_location(this, result) } /** Holds if this method is an extension method. */ - predicate isExtensionMethod() { - getParameter(0).hasExtensionMethodModifier() - } + predicate isExtensionMethod() { getParameter(0).hasExtensionMethodModifier() } /** Gets the type of the `params` parameter of this method, if any. */ Type getParamsType() { - exists(Parameter last | - last = getParameter(getNumberOfParameters() - 1) | + exists(Parameter last | last = getParameter(getNumberOfParameters() - 1) | last.isParams() and result = last.getType().(ArrayType).getElementType() ) @@ -314,9 +274,7 @@ class Method extends Callable, Virtualizable, Attributable, @method { predicate hasParams() { exists(getParamsType()) } // Remove when `Callable.isOverridden()` is removed - override predicate isOverridden() { - Virtualizable.super.isOverridden() - } + override predicate isOverridden() { Virtualizable.super.isOverridden() } override predicate fromSource() { Callable.super.fromSource() and @@ -328,9 +286,7 @@ class Method extends Callable, Virtualizable, Attributable, @method { override Location getLocation() { result = Callable.super.getLocation() } override Parameter getRawParameter(int i) { - if this.isStatic() - then result = this.getParameter(i) - else result = this.getParameter(i-1) + if this.isStatic() then result = this.getParameter(i) else result = this.getParameter(i - 1) } } @@ -344,13 +300,9 @@ class Method extends Callable, Virtualizable, Attributable, @method { * ``` */ class ExtensionMethod extends Method { - ExtensionMethod() { - this.isExtensionMethod() - } + ExtensionMethod() { this.isExtensionMethod() } - override predicate isStatic() { - any() - } + override predicate isStatic() { any() } /** Gets the type being extended by this method. */ Type getExtendedType() { result = getParameter(0).getType() } @@ -366,8 +318,7 @@ class ExtensionMethod extends Method { * ``` */ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @constructor { - - override string getName() { constructors(this,result,_,_) } + override string getName() { constructors(this, result, _, _) } override Type getReturnType() { exists(this) and // needed to avoid compiler warning @@ -393,9 +344,9 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @ /** Holds if this constructor has an initializer. */ predicate hasInitializer() { exists(getInitializer()) } - override ValueOrRefType getDeclaringType() { constructors(this,_,result,_) } + override ValueOrRefType getDeclaringType() { constructors(this, _, result, _) } - override Constructor getSourceDeclaration() { constructors(this,_,_,result) } + override Constructor getSourceDeclaration() { constructors(this, _, _, result) } override Location getALocation() { constructor_location(this, result) } @@ -406,9 +357,7 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @ override Location getLocation() { result = Callable.super.getLocation() } override Parameter getRawParameter(int i) { - if this.isStatic() - then result = this.getParameter(i) - else result = this.getParameter(i-1) + if this.isStatic() then result = this.getParameter(i) else result = this.getParameter(i - 1) } override string getUndecoratedName() { result = ".ctor" } @@ -425,7 +374,6 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @ * ``` */ class StaticConstructor extends Constructor { - StaticConstructor() { this.isStatic() } override string getUndecoratedName() { result = ".cctor" } @@ -441,10 +389,7 @@ class StaticConstructor extends Constructor { * } * ``` */ -class InstanceConstructor extends Constructor { - - InstanceConstructor() { not this.isStatic() } -} +class InstanceConstructor extends Constructor { InstanceConstructor() { not this.isStatic() } } /** * A destructor, for example `~C() { }` on line 2 in @@ -456,8 +401,7 @@ class InstanceConstructor extends Constructor { * ``` */ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @destructor { - - override string getName() { destructors(this,result,_,_) } + override string getName() { destructors(this, result, _, _) } override Type getReturnType() { exists(this) and // needed to avoid compiler warning @@ -466,9 +410,9 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de override string getUndecoratedName() { result = "Finalize" } - override ValueOrRefType getDeclaringType() { destructors(this,_,result,_) } + override ValueOrRefType getDeclaringType() { destructors(this, _, result, _) } - override Destructor getSourceDeclaration() { destructors(this,_,_,result) } + override Destructor getSourceDeclaration() { destructors(this, _, _, result) } override Location getALocation() { destructor_location(this, result) } @@ -484,19 +428,18 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de * (`BinaryOperator`), or a conversion operator (`ConversionOperator`). */ class Operator extends Callable, Member, Attributable, @operator { - /** Gets the assembly name of this operator. */ - string getAssemblyName() { operators(this,result,_,_,_,_) } + string getAssemblyName() { operators(this, result, _, _, _, _) } - override string getName() { operators(this,_,result,_,_,_) } + override string getName() { operators(this, _, result, _, _, _) } string getFunctionName() { none() } - override ValueOrRefType getDeclaringType() { operators(this,_,_,result,_,_) } + override ValueOrRefType getDeclaringType() { operators(this, _, _, result, _, _) } - override Type getReturnType() { operators(this,_,_,_,getTypeRef(result),_) } + override Type getReturnType() { operators(this, _, _, _, getTypeRef(result), _) } - override Operator getSourceDeclaration() { operators(this,_,_,_,_,result) } + override Operator getSourceDeclaration() { operators(this, _, _, _, _, result) } override Location getALocation() { operator_location(this, result) } @@ -507,7 +450,6 @@ class Operator extends Callable, Member, Attributable, @operator { override Parameter getRawParameter(int i) { result = getParameter(i) } } - /** * A user-defined unary operator - an operator taking one operand. * @@ -518,7 +460,6 @@ class Operator extends Callable, Member, Attributable, @operator { * (`DecrementOperator`). */ class UnaryOperator extends Operator { - UnaryOperator() { this.getNumberOfParameters() = 1 and not this instanceof ConversionOperator @@ -535,7 +476,6 @@ class UnaryOperator extends Operator { * ``` */ class PlusOperator extends UnaryOperator { - PlusOperator() { this.getName() = "+" } override string getFunctionName() { result = "op_UnaryPlus" } @@ -551,7 +491,6 @@ class PlusOperator extends UnaryOperator { * ``` */ class MinusOperator extends UnaryOperator { - MinusOperator() { this.getName() = "-" } override string getFunctionName() { result = "op_UnaryNegation" } @@ -567,7 +506,6 @@ class MinusOperator extends UnaryOperator { * ``` */ class NotOperator extends UnaryOperator { - NotOperator() { this.getName() = "!" } override string getFunctionName() { result = "op_LogicalNot" } @@ -583,7 +521,6 @@ class NotOperator extends UnaryOperator { * ``` */ class ComplementOperator extends UnaryOperator { - ComplementOperator() { this.getName() = "~" } override string getFunctionName() { result = "op_OnesComplement" } @@ -599,7 +536,6 @@ class ComplementOperator extends UnaryOperator { * ``` */ class IncrementOperator extends UnaryOperator { - IncrementOperator() { this.getName() = "++" } override string getFunctionName() { result = "op_Increment" } @@ -615,7 +551,6 @@ class IncrementOperator extends UnaryOperator { * ``` */ class DecrementOperator extends UnaryOperator { - DecrementOperator() { this.getName() = "--" } override string getFunctionName() { result = "op_Decrement" } @@ -631,7 +566,6 @@ class DecrementOperator extends UnaryOperator { * ``` */ class FalseOperator extends UnaryOperator { - FalseOperator() { this.getName() = "false" } override string getFunctionName() { result = "op_False" } @@ -647,7 +581,6 @@ class FalseOperator extends UnaryOperator { * ``` */ class TrueOperator extends UnaryOperator { - TrueOperator() { this.getName() = "true" } override string getFunctionName() { result = "op_True" } @@ -666,10 +599,7 @@ class TrueOperator extends UnaryOperator { * a greater than operator (`GTOperator`), a less than or equals operator * (`LEOperator`), or a greater than or equals operator (`GEOperator`). */ -class BinaryOperator extends Operator { - - BinaryOperator() { this.getNumberOfParameters() = 2 } -} +class BinaryOperator extends Operator { BinaryOperator() { this.getNumberOfParameters() = 2 } } /** * A user-defined addition operator (`+`), for example @@ -681,7 +611,6 @@ class BinaryOperator extends Operator { * ``` */ class AddOperator extends BinaryOperator { - AddOperator() { this.getName() = "+" } override string getFunctionName() { result = "op_Addition" } @@ -697,7 +626,6 @@ class AddOperator extends BinaryOperator { * ``` */ class SubOperator extends BinaryOperator { - SubOperator() { this.getName() = "-" } override string getFunctionName() { result = "op_Subtraction" } @@ -713,7 +641,6 @@ class SubOperator extends BinaryOperator { * ``` */ class MulOperator extends BinaryOperator { - MulOperator() { this.getName() = "*" } override string getFunctionName() { result = "op_Multiply" } @@ -729,7 +656,6 @@ class MulOperator extends BinaryOperator { * ``` */ class DivOperator extends BinaryOperator { - DivOperator() { this.getName() = "/" } override string getFunctionName() { result = "op_Division" } @@ -745,7 +671,6 @@ class DivOperator extends BinaryOperator { * ``` */ class RemOperator extends BinaryOperator { - RemOperator() { this.getName() = "%" } override string getFunctionName() { result = "op_Modulus" } @@ -761,7 +686,6 @@ class RemOperator extends BinaryOperator { * ``` */ class AndOperator extends BinaryOperator { - AndOperator() { this.getName() = "&" } override string getFunctionName() { result = "op_BitwiseAnd" } @@ -777,7 +701,6 @@ class AndOperator extends BinaryOperator { * ``` */ class OrOperator extends BinaryOperator { - OrOperator() { this.getName() = "|" } override string getFunctionName() { result = "op_BitwiseOr" } @@ -793,7 +716,6 @@ class OrOperator extends BinaryOperator { * ``` */ class XorOperator extends BinaryOperator { - XorOperator() { this.getName() = "^" } override string getFunctionName() { result = "op_ExclusiveOr" } @@ -809,7 +731,6 @@ class XorOperator extends BinaryOperator { * ``` */ class LShiftOperator extends BinaryOperator { - LShiftOperator() { this.getName() = "<<" } override string getFunctionName() { result = "op_LeftShift" } @@ -825,7 +746,6 @@ class LShiftOperator extends BinaryOperator { * ``` */ class RShiftOperator extends BinaryOperator { - RShiftOperator() { this.getName() = ">>" } override string getFunctionName() { result = "op_RightShift" } @@ -841,7 +761,6 @@ class RShiftOperator extends BinaryOperator { * ``` */ class EQOperator extends BinaryOperator { - EQOperator() { this.getName() = "==" } override string getFunctionName() { result = "op_Equality" } @@ -857,7 +776,6 @@ class EQOperator extends BinaryOperator { * ``` */ class NEOperator extends BinaryOperator { - NEOperator() { this.getName() = "!=" } override string getFunctionName() { result = "op_Inequality" } @@ -873,7 +791,6 @@ class NEOperator extends BinaryOperator { * ``` */ class LTOperator extends BinaryOperator { - LTOperator() { this.getName() = "<" } override string getFunctionName() { result = "op_LessThan" } @@ -889,7 +806,6 @@ class LTOperator extends BinaryOperator { * ``` */ class GTOperator extends BinaryOperator { - GTOperator() { this.getName() = ">" } override string getFunctionName() { result = "op_GreaterThan" } @@ -905,7 +821,6 @@ class GTOperator extends BinaryOperator { * ``` */ class LEOperator extends BinaryOperator { - LEOperator() { this.getName() = "<=" } override string getFunctionName() { result = "op_LessThanOrEqual" } @@ -921,7 +836,6 @@ class LEOperator extends BinaryOperator { * ``` */ class GEOperator extends BinaryOperator { - GEOperator() { this.getName() = ">=" } override string getFunctionName() { result = "op_GreaterThanOrEqual" } @@ -937,7 +851,6 @@ class GEOperator extends BinaryOperator { * ``` */ class ConversionOperator extends Operator { - ConversionOperator() { this.getName() = "implicit conversion" or this.getName() = "explicit conversion" @@ -960,10 +873,7 @@ class ConversionOperator extends Operator { * ``` */ class ImplicitConversionOperator extends ConversionOperator { - - ImplicitConversionOperator() { - this.getName() = "implicit conversion" - } + ImplicitConversionOperator() { this.getName() = "implicit conversion" } override string getFunctionName() { result = "op_Implicit" } } @@ -978,10 +888,7 @@ class ImplicitConversionOperator extends ConversionOperator { * ``` */ class ExplicitConversionOperator extends ConversionOperator { - - ExplicitConversionOperator() { - this.getName() = "explicit conversion" - } + ExplicitConversionOperator() { this.getName() = "explicit conversion" } override string getFunctionName() { result = "op_Explicit" } } @@ -1001,41 +908,25 @@ class ExplicitConversionOperator extends ConversionOperator { * ``` */ class LocalFunction extends Callable, @local_function { - override string getName() { - local_functions(this, result, _, _) - } + override string getName() { local_functions(this, result, _, _) } - override LocalFunction getSourceDeclaration() { - local_functions(this, _, _, result) - } + override LocalFunction getSourceDeclaration() { local_functions(this, _, _, result) } - override Type getReturnType() { - local_functions(this, _, result, _) - } + override Type getReturnType() { local_functions(this, _, result, _) } - override Element getParent() { - result = getStatement().getParent() - } + override Element getParent() { result = getStatement().getParent() } /** Gets the local function statement defining this function. */ - LocalFunctionStmt getStatement() { - result.getLocalFunction() = getSourceDeclaration() - } + LocalFunctionStmt getStatement() { result.getLocalFunction() = getSourceDeclaration() } - override Callable getEnclosingCallable() { - result = this.getStatement().getEnclosingCallable() - } + override Callable getEnclosingCallable() { result = this.getStatement().getEnclosingCallable() } override predicate hasQualifiedName(string qualifier, string name) { qualifier = this.getEnclosingCallable().getQualifiedName() and name = this.getName() } - override Location getALocation() { - result = getStatement().getALocation() - } + override Location getALocation() { result = getStatement().getALocation() } - override Parameter getRawParameter(int i) { - result = getParameter(i) - } + override Parameter getRawParameter(int i) { result = getParameter(i) } } diff --git a/csharp/ql/src/semmle/code/csharp/Chaining.qll b/csharp/ql/src/semmle/code/csharp/Chaining.qll index 555db4935fb..b4f5ee66f8f 100644 --- a/csharp/ql/src/semmle/code/csharp/Chaining.qll +++ b/csharp/ql/src/semmle/code/csharp/Chaining.qll @@ -19,20 +19,14 @@ import csharp * callable), the return type of `c` must be a subtype of `c`'s * declaring type, and `c` must be non-static. */ -predicate designedForChaining(Callable c) { - not nonChaining(c) -} +predicate designedForChaining(Callable c) { not nonChaining(c) } private predicate nonChaining(Callable c) { exists(Type t | t = c.getDeclaringType() | not t instanceof RefType) or - exists(Method override | - override.getOverridee() = c | - nonChaining(override) - ) + exists(Method override | override.getOverridee() = c | nonChaining(override)) or - exists(Getter override | - override.getDeclaration().getOverridee() = c.(Getter).getDeclaration() | + exists(Getter override | override.getDeclaration().getOverridee() = c.(Getter).getDeclaration() | nonChaining(override) ) or @@ -47,25 +41,24 @@ private predicate nonChainingBody(Callable c) { } private Expr returnedValue(Callable c) { - exists(Expr e | - c.canReturn(e) | - if e instanceof ConditionalExpr then + exists(Expr e | c.canReturn(e) | + if e instanceof ConditionalExpr + then result = e.(ConditionalExpr).getThen() or result = e.(ConditionalExpr).getElse() - else - result = e + else result = e ) } /** Holds if `c` can return a non-`this` value. */ private predicate nonChainingReturn(Callable c) { - exists(Expr ret | - ret = returnedValue(c) | + exists(Expr ret | ret = returnedValue(c) | // The result of a call is returned - exists(Callable other | - other = ret.(Call).getTarget() | - nonChaining(other) or - exists(MethodCall mc | mc = ret | not mc.hasThisQualifier()) or + exists(Callable other | other = ret.(Call).getTarget() | + nonChaining(other) + or + exists(MethodCall mc | mc = ret | not mc.hasThisQualifier()) + or exists(MemberAccess ma | ma = ret | not ma.hasThisQualifier()) ) or diff --git a/csharp/ql/src/semmle/code/csharp/Comments.qll b/csharp/ql/src/semmle/code/csharp/Comments.qll index c87c9745ab4..6802e933152 100644 --- a/csharp/ql/src/semmle/code/csharp/Comments.qll +++ b/csharp/ql/src/semmle/code/csharp/Comments.qll @@ -14,22 +14,21 @@ import Location * Either a single line comment (`SingleLineComment`), an XML comment (`XmlComment`), * or a line in a multi-line comment (`MultilineComment`). */ -class CommentLine extends @commentline -{ +class CommentLine extends @commentline { /** Gets a textual representation of this comment line. */ string toString() { none() } /** Gets the location of this comment line. */ - Location getLocation() { commentline_location(this,result) } + Location getLocation() { commentline_location(this, result) } /** Gets the containing comment block. */ CommentBlock getParent() { result.getAChild() = this } /** Gets the text in the comment, trimmed to remove comment markers and leading and trailing whitespace. */ - string getText() { commentline(this,_,result,_) } + string getText() { commentline(this, _, result, _) } /** Gets the raw text of the comment, including the comment markers. */ - string getRawText() { commentline(this,_,_,result) } + string getRawText() { commentline(this, _, _, result) } } /** @@ -40,9 +39,8 @@ class CommentLine extends @commentline * public int Succ(int x) => x + 1; * ``` */ -class SinglelineComment extends CommentLine, @singlelinecomment -{ - override string toString() { result="// ..." } +class SinglelineComment extends CommentLine, @singlelinecomment { + override string toString() { result = "// ..." } } /** @@ -54,9 +52,8 @@ class SinglelineComment extends CommentLine, @singlelinecomment * a comment * / * ``` */ -class MultilineComment extends CommentLine, @multilinecomment -{ - override string toString() { result="/* ... */" } +class MultilineComment extends CommentLine, @multilinecomment { + override string toString() { result = "/* ... */" } } /** @@ -69,79 +66,79 @@ class MultilineComment extends CommentLine, @multilinecomment * /// * ``` */ -class XmlComment extends CommentLine, @xmldoccomment -{ - override string toString() { result="/// ..." } +class XmlComment extends CommentLine, @xmldoccomment { + override string toString() { result = "/// ..." } - private string xmlAttributeRegex() - { result = "(" + xmlIdentifierRegex() + ")(?:\\s*=\\s*[\"']([^\"']*)[\"'])" } + private string xmlAttributeRegex() { + result = "(" + xmlIdentifierRegex() + ")(?:\\s*=\\s*[\"']([^\"']*)[\"'])" + } - private string xmlIdentifierRegex() - { result = "\\w+" } + private string xmlIdentifierRegex() { result = "\\w+" } - private string xmlTagOpenRegex() - { result = "<\\s*" + xmlIdentifierRegex() } + private string xmlTagOpenRegex() { result = "<\\s*" + xmlIdentifierRegex() } - private string xmlTagIntroRegex() - { result = xmlTagOpenRegex() + "(?:\\s*" + xmlAttributeRegex() +")*" } + private string xmlTagIntroRegex() { + result = xmlTagOpenRegex() + "(?:\\s*" + xmlAttributeRegex() + ")*" + } - private string xmlTagCloseRegex() - { result = "" } + private string xmlTagCloseRegex() { result = "" } /** Gets the text inside the XML element at character offset `offset`. */ - private string getElement(int offset) - { - result = getText().regexpFind(xmlTagIntroRegex(),_,offset) + private string getElement(int offset) { + result = getText().regexpFind(xmlTagIntroRegex(), _, offset) } /** Gets the name of the opening tag at offset `offset`. */ - string getOpenTag(int offset) - { - exists(int offset1,int offset2 | - result = getElement(offset1).regexpFind(xmlIdentifierRegex(),0,offset2) - and offset = offset1+offset2 ) + string getOpenTag(int offset) { + exists(int offset1, int offset2 | + result = getElement(offset1).regexpFind(xmlIdentifierRegex(), 0, offset2) and + offset = offset1 + offset2 + ) } /** Gets the name of the closing tag at offset `offset`. */ - string getCloseTag(int offset) - { + string getCloseTag(int offset) { exists(int offset1, int offset2 | - result = getText().regexpFind(xmlTagCloseRegex(),_,offset1). - regexpFind(xmlIdentifierRegex(),0,offset2) - and offset = offset1+offset2 ) + result = getText() + .regexpFind(xmlTagCloseRegex(), _, offset1) + .regexpFind(xmlIdentifierRegex(), 0, offset2) and + offset = offset1 + offset2 + ) } /** Gets the name of the empty tag at offset `offset`. */ - string getEmptyTag(int offset) - { + string getEmptyTag(int offset) { exists(int offset1, int offset2 | ( - result=getText().regexpFind(xmlTagIntroRegex() + "\\s*/>",_,offset1). - regexpFind(xmlIdentifierRegex(),0,offset2) - or result=getText().regexpFind(xmlTagIntroRegex() + "\\s*>\\s*",_,offset1). - regexpFind(xmlIdentifierRegex(),0,offset2) - ) and offset=offset1+offset2 ) + result = getText() + .regexpFind(xmlTagIntroRegex() + "\\s*/>", _, offset1) + .regexpFind(xmlIdentifierRegex(), 0, offset2) or + result = getText() + .regexpFind(xmlTagIntroRegex() + "\\s*>\\s*", _, + offset1) + .regexpFind(xmlIdentifierRegex(), 0, offset2) + ) and + offset = offset1 + offset2 + ) } /** * Gets the XML attribute value for an XML element, * for a given XML attribute name `key` and element offset `offset`. */ - string getAttribute(string element, string key, int offset) - { - exists(int offset1, int offset2, string elt, string pair | - elt = getElement(offset1) | - element = elt.regexpFind(xmlIdentifierRegex(),0,offset2) - and offset = offset1+offset2 - and pair = elt.regexpFind(xmlAttributeRegex(),_,_) - and key = pair.regexpCapture(xmlAttributeRegex(),1) - and result = pair.regexpCapture(xmlAttributeRegex(),2) ) + string getAttribute(string element, string key, int offset) { + exists(int offset1, int offset2, string elt, string pair | elt = getElement(offset1) | + element = elt.regexpFind(xmlIdentifierRegex(), 0, offset2) and + offset = offset1 + offset2 and + pair = elt.regexpFind(xmlAttributeRegex(), _, _) and + key = pair.regexpCapture(xmlAttributeRegex(), 1) and + result = pair.regexpCapture(xmlAttributeRegex(), 2) + ) } /** Holds if the XML element at the given offset is not empty. */ - predicate hasBody(string element, int offset) - { - element=getOpenTag(offset) and not element=getEmptyTag(offset) + predicate hasBody(string element, int offset) { + element = getOpenTag(offset) and not element = getEmptyTag(offset) } } @@ -154,40 +151,39 @@ class XmlComment extends CommentLine, @xmldoccomment * /// * ``` */ -class CommentBlock extends @commentblock -{ +class CommentBlock extends @commentblock { /** Gets a textual representation of this comment block. */ - string toString() { result=getChild(0).toString() } + string toString() { result = getChild(0).toString() } /** Gets the location of this comment block */ - Location getLocation() { commentblock_location(this,result) } + Location getLocation() { commentblock_location(this, result) } /** Gets the number of lines in this comment block. */ - int getNumLines() { result=count(getAChild()) } + int getNumLines() { result = count(getAChild()) } /** Gets the `c`th child of this comment block (numbered from 0). */ - CommentLine getChild(int c) { commentblock_child(this,result,c) } + CommentLine getChild(int c) { commentblock_child(this, result, c) } /** Gets a comment line in this comment block. */ - CommentLine getAChild() { commentblock_child(this,result,_) } + CommentLine getAChild() { commentblock_child(this, result, _) } /** Gets the `Element` that contains this comment block, if any. */ - Element getParent() { commentblock_binding(this,result,0) } + Element getParent() { commentblock_binding(this, result, 0) } /** Gets the `Element` that this comment block most probably refers to. */ - Element getElement() { commentblock_binding(this,result,1) } + Element getElement() { commentblock_binding(this, result, 1) } /** Gets the `Element` before this comment block, if any. */ - Element getBefore() { commentblock_binding(this,result,2) } + Element getBefore() { commentblock_binding(this, result, 2) } /** Gets the `Element` after this comment, if any. */ - Element getAfter(){ commentblock_binding(this,result,3) } + Element getAfter() { commentblock_binding(this, result, 3) } /** * Gets an `Element` possibly associated with this comment. * This is a superset of `getElement()`. */ - Element getAnElement() { commentblock_binding(this,result,_) } + Element getAnElement() { commentblock_binding(this, result, _) } /** Gets a line of text in this comment block. */ string getALine() { result = getAChild().getText() } @@ -196,24 +192,19 @@ class CommentBlock extends @commentblock predicate isOrphan() { not exists(getElement()) } /** Holds if this block consists entirely of XML comments. */ - predicate isXmlCommentBlock() - { - forall(CommentLine l | l = getAChild() | l instanceof XmlComment ) + predicate isXmlCommentBlock() { + forall(CommentLine l | l = getAChild() | l instanceof XmlComment) } /** Gets a `CommentLine` containing text. */ - CommentLine getANonEmptyLine() - { - result = getAChild() and result.getText().length()!=0 - } + CommentLine getANonEmptyLine() { result = getAChild() and result.getText().length() != 0 } /** Gets a `CommentLine` that might contain code. */ - CommentLine getAProbableCodeLine() - { + CommentLine getAProbableCodeLine() { // Logic taken verbatim from Java query CommentedCode.qll - result=getAChild() and - exists(string trimmed | - trimmed = result.getText().regexpReplaceAll("\\s*//.*$", "") | - trimmed.matches("%;") or trimmed.matches("%{") or trimmed.matches("%}")) + result = getAChild() and + exists(string trimmed | trimmed = result.getText().regexpReplaceAll("\\s*//.*$", "") | + trimmed.matches("%;") or trimmed.matches("%{") or trimmed.matches("%}") + ) } } diff --git a/csharp/ql/src/semmle/code/csharp/Conversion.qll b/csharp/ql/src/semmle/code/csharp/Conversion.qll index a9709221dcc..63ab98e1675 100644 --- a/csharp/ql/src/semmle/code/csharp/Conversion.qll +++ b/csharp/ql/src/semmle/code/csharp/Conversion.qll @@ -55,27 +55,20 @@ private predicate implicitConversionNonNull(Type fromType, Type toType) { } private Type getTypeArgument(UnboundGenericType ugt, ConstructedType ct, int i, TypeParameter tp) { - ct.getUnboundGeneric() = ugt - and - not ugt instanceof AnonymousClass - and - tp = ugt.getTypeParameter(i) - and + ct.getUnboundGeneric() = ugt and + not ugt instanceof AnonymousClass and + tp = ugt.getTypeParameter(i) and result = ct.getTypeArgument(i) } /** A type that is an element type of an array type. */ private class ArrayElementType extends Type { - ArrayElementType() { - this = any(ArrayType at).getElementType() - } + ArrayElementType() { this = any(ArrayType at).getElementType() } } /** A type that is an argument in a constructed type. */ private class TypeArgument extends Type { - TypeArgument() { - this = any(ConstructedType ct).getATypeArgument() - } + TypeArgument() { this = any(ConstructedType ct).getATypeArgument() } } /** @@ -97,14 +90,13 @@ predicate convIdentity(Type fromType, Type toType) { private module Identity { private class IdentityConvertibleType extends Type { - IdentityConvertibleType() { - isIdentityConvertible(this) - } + IdentityConvertibleType() { isIdentityConvertible(this) } } private class IdentityConvertibleArrayType extends IdentityConvertibleType, ArrayType { } - private class IdentityConvertibleConstructedType extends IdentityConvertibleType, ConstructedType { } + private class IdentityConvertibleConstructedType extends IdentityConvertibleType, ConstructedType { + } /** * A type is (strictly) identity convertible if it contains at least one `object` @@ -130,20 +122,24 @@ private module Identity { convIdentityStrictConstructedType(fromType, toType) } - private predicate convIdentityObjectDynamic(ObjectType fromType, DynamicType toType) { - any() - } + private predicate convIdentityObjectDynamic(ObjectType fromType, DynamicType toType) { any() } - private predicate convIdentityStrictArrayType(IdentityConvertibleArrayType fromType, IdentityConvertibleArrayType toType) { + private predicate convIdentityStrictArrayType( + IdentityConvertibleArrayType fromType, IdentityConvertibleArrayType toType + ) { convIdentityStrictArrayTypeJoin(fromType, toType, toType.getDimension(), toType.getRank()) } pragma[noinline] - private predicate convIdentityStrictArrayTypeJoin(IdentityConvertibleArrayType fromType, IdentityConvertibleArrayType toType, int dim, int rnk) { + private predicate convIdentityStrictArrayTypeJoin( + IdentityConvertibleArrayType fromType, IdentityConvertibleArrayType toType, int dim, int rnk + ) { convIdentityStrictArrayElementType(fromType, toType.getElementType(), dim, rnk) } - private predicate convIdentityStrictArrayElementType(IdentityConvertibleArrayType fromType, ArrayElementType aet, int dim, int rnk) { + private predicate convIdentityStrictArrayElementType( + IdentityConvertibleArrayType fromType, ArrayElementType aet, int dim, int rnk + ) { convIdentityStrict(fromType.getElementType(), aet) and dim = fromType.getDimension() and rnk = fromType.getRank() @@ -155,22 +151,20 @@ private module Identity { */ private int getTypeArgumentCount(UnboundGenericType ugt, int i) { result = strictcount(Type arg | - exists(IdentityConvertibleConstructedType ct | - ct.getUnboundGeneric() = ugt | - arg = ct.getTypeArgument(i) + exists(IdentityConvertibleConstructedType ct | ct.getUnboundGeneric() = ugt | + arg = ct.getTypeArgument(i) + ) ) - ) } private int rnk(UnboundGenericType ugt, int i) { - result = rank[i + 1](int j, int k | - j = getTypeArgumentCount(ugt, k) | - k order by j, k - ) + result = rank[i + 1](int j, int k | j = getTypeArgumentCount(ugt, k) | k order by j, k) } /** Gets the 'i'th type argument, ranked by size, of constructed type `t`. */ - private Type getTypeArgumentRanked(UnboundGenericType ugt, IdentityConvertibleConstructedType t, int i) { + private Type getTypeArgumentRanked( + UnboundGenericType ugt, IdentityConvertibleConstructedType t, int i + ) { result = getTypeArgument(ugt, t, rnk(ugt, i), _) } @@ -183,14 +177,17 @@ private module Identity { exists(int j | fromTypeArgument = getTypeArgumentRanked(_, _, i) and toTypeArgument = getTypeArgumentRanked(_, _, j) and - i <= j and j <= i - | + i <= j and + j <= i + | convIdentity(fromTypeArgument, toTypeArgument) ) } pragma[nomagic] - private predicate convTypeArgumentsSomeUnbound(UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i) { + private predicate convTypeArgumentsSomeUnbound( + UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i + ) { convTypeArguments(fromTypeArgument, toTypeArgument, i) and fromTypeArgument = getTypeArgumentRanked(ugt, _, i) } @@ -201,13 +198,18 @@ private module Identity { * based on unbound generic type `ugt`. */ pragma[noinline] - private predicate convTypeArgumentsSameUnbound(UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i) { + private predicate convTypeArgumentsSameUnbound( + UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i + ) { convTypeArgumentsSomeUnbound(ugt, fromTypeArgument, toTypeArgument, i) and toTypeArgument = getTypeArgumentRanked(ugt, _, i) } pragma[nomagic] - private predicate convIdentitySingle0(UnboundGenericType ugt, IdentityConvertibleConstructedType toType, TypeArgument fromTypeArgument, TypeArgument toTypeArgument) { + private predicate convIdentitySingle0( + UnboundGenericType ugt, IdentityConvertibleConstructedType toType, + TypeArgument fromTypeArgument, TypeArgument toTypeArgument + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, 0) and toTypeArgument = getTypeArgumentRanked(ugt, toType, 0) and ugt.getNumberOfTypeParameters() = 1 @@ -217,22 +219,32 @@ private module Identity { * Holds if the type arguments of types `fromType` and `toType` are identity * convertible, and the number of type arguments is 1. */ - predicate convIdentitySingle(UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType) { + predicate convIdentitySingle( + UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, + IdentityConvertibleConstructedType toType + ) { exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument | - convIdentitySingle0(ugt, toType, fromTypeArgument, toTypeArgument) | + convIdentitySingle0(ugt, toType, fromTypeArgument, toTypeArgument) + | fromTypeArgument = getTypeArgumentRanked(ugt, fromType, 0) ) } pragma[nomagic] - private predicate convIdentityMultiple01Aux0(UnboundGenericType ugt, IdentityConvertibleConstructedType toType, TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument toTypeArgument1) { + private predicate convIdentityMultiple01Aux0( + UnboundGenericType ugt, IdentityConvertibleConstructedType toType, + TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument toTypeArgument1 + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument0, toTypeArgument0, 0) and toTypeArgument0 = getTypeArgumentRanked(ugt, toType, 0) and toTypeArgument1 = getTypeArgumentRanked(ugt, toType, 1) } pragma[nomagic] - private predicate convIdentityMultiple01Aux1(UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, TypeArgument fromTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1) { + private predicate convIdentityMultiple01Aux1( + UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, + TypeArgument fromTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1 + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument1, toTypeArgument1, 1) and fromTypeArgument0 = getTypeArgumentRanked(ugt, fromType, 0) and fromTypeArgument1 = getTypeArgumentRanked(ugt, fromType, 1) @@ -242,23 +254,37 @@ private module Identity { * Holds if the first two ranked type arguments of types `fromType` and `toType` * are identity convertible. */ - private predicate convIdentityMultiple01(UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType) { - exists(Type fromTypeArgument0, Type toTypeArgument0, Type fromTypeArgument1, Type toTypeArgument1 | - convIdentityMultiple01Aux0(ugt, toType, fromTypeArgument0, toTypeArgument0, toTypeArgument1) | - convIdentityMultiple01Aux1(ugt, fromType, fromTypeArgument0, fromTypeArgument1, toTypeArgument1) + private predicate convIdentityMultiple01( + UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, + IdentityConvertibleConstructedType toType + ) { + exists( + Type fromTypeArgument0, Type toTypeArgument0, Type fromTypeArgument1, Type toTypeArgument1 + | + convIdentityMultiple01Aux0(ugt, toType, fromTypeArgument0, toTypeArgument0, toTypeArgument1) + | + convIdentityMultiple01Aux1(ugt, fromType, fromTypeArgument0, fromTypeArgument1, + toTypeArgument1) ) } pragma[nomagic] - private predicate convIdentityMultiple2Aux(UnboundGenericType ugt, IdentityConvertibleConstructedType toType, int i, TypeArgument fromTypeArgument, TypeArgument toTypeArgument) { + private predicate convIdentityMultiple2Aux( + UnboundGenericType ugt, IdentityConvertibleConstructedType toType, int i, + TypeArgument fromTypeArgument, TypeArgument toTypeArgument + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, i) and toTypeArgument = getTypeArgumentRanked(ugt, toType, i) and i >= 2 } - private predicate convIdentityMultiple2(UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType, int i) { + private predicate convIdentityMultiple2( + UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, + IdentityConvertibleConstructedType toType, int i + ) { exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument | - convIdentityMultiple2Aux(ugt, toType, i, fromTypeArgument, toTypeArgument) | + convIdentityMultiple2Aux(ugt, toType, i, fromTypeArgument, toTypeArgument) + | fromTypeArgument = getTypeArgumentRanked(ugt, fromType, i) ) } @@ -268,30 +294,35 @@ private module Identity { * `fromType` and `toType` are identity convertible. */ pragma[nomagic] - predicate convIdentityMultiple(UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType, int i) { + predicate convIdentityMultiple( + UnboundGenericType ugt, IdentityConvertibleConstructedType fromType, + IdentityConvertibleConstructedType toType, int i + ) { convIdentityMultiple01(ugt, fromType, toType) and i = 1 or convIdentityMultiple(ugt, fromType, toType, i - 1) and convIdentityMultiple2(ugt, fromType, toType, i) } - private predicate convIdentityStrictConstructedType(IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType) { - /* Semantically equivalent with - * ``` - * ugt = fromType.getUnboundGeneric() - * and - * forex(int i | - * i in [0 .. ugt.getNumberOfTypeParameters() - 1] | - * exists(Type t1, Type t2 | - * t1 = getTypeArgument(ugt, fromType, i, _) and - * t2 = getTypeArgument(ugt, toType, i, _) | - * convIdentity(t1, t2) - * ) - * ) - * ``` - * but performance is improved by explicitly evaluating the `i`th argument - * only when all preceding arguments are convertible. - */ + private predicate convIdentityStrictConstructedType( + IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType + ) { + // Semantically equivalent with + // ``` + // ugt = fromType.getUnboundGeneric() + // and + // forex(int i | + // i in [0 .. ugt.getNumberOfTypeParameters() - 1] | + // exists(Type t1, Type t2 | + // t1 = getTypeArgument(ugt, fromType, i, _) and + // t2 = getTypeArgument(ugt, toType, i, _) | + // convIdentity(t1, t2) + // ) + // ) + // ``` + // but performance is improved by explicitly evaluating the `i`th argument + // only when all preceding arguments are convertible. + // fromType != toType and ( convIdentitySingle(_, fromType, toType) @@ -409,9 +440,7 @@ private predicate convNumericChar(SimpleType toType) { toType instanceof DecimalType } -private predicate convNumericFloat(SimpleType toType) { - toType instanceof DoubleType -} +private predicate convNumericFloat(SimpleType toType) { toType instanceof DoubleType } /** * INTERNAL: Do not use. @@ -421,10 +450,8 @@ private predicate convNumericFloat(SimpleType toType) { * 6.1.4: Implicit nullable conversions. */ predicate convNullableType(ValueOrRefType fromType, NullableType toType) { - exists(ValueType vt1, ValueType vt2 | - implicitConversionNonNull(vt1, vt2) | - toType.getUnderlyingType() = vt2 - and + exists(ValueType vt1, ValueType vt2 | implicitConversionNonNull(vt1, vt2) | + toType.getUnderlyingType() = vt2 and ( fromType = vt1 or @@ -433,13 +460,10 @@ predicate convNullableType(ValueOrRefType fromType, NullableType toType) { ) } -/* - * This is a deliberate, small Cartesian product, so we have manually lifted it to force the - * evaluator to evaluate it in its entirety, rather than trying to optimize it in context. - */ +// This is a deliberate, small Cartesian product, so we have manually lifted it to force the +// evaluator to evaluate it in its entirety, rather than trying to optimize it in context. pragma[noinline] -private -predicate defaultNullConversion(Type fromType, Type toType) { +private predicate defaultNullConversion(Type fromType, Type toType) { fromType instanceof NullType and convNullType(toType) } @@ -462,19 +486,15 @@ private predicate convRefTypeNonNull(Type fromType, Type toType) { convRefTypeParameter(fromType, toType) } -/* - * This is a deliberate, small cartesian product, so we have manually lifted it to force the - * evaluator to evaluate it in its entirety, rather than trying to optimize it in context. - */ +// This is a deliberate, small cartesian product, so we have manually lifted it to force the +// evaluator to evaluate it in its entirety, rather than trying to optimize it in context. pragma[noinline] private predicate defaultDynamicConversion(Type fromType, Type toType) { fromType instanceof RefType and toType instanceof DynamicType } -/* - * This is a deliberate, small cartesian product, so we have manually lifted it to force the - * evaluator to evaluate it in its entirety, rather than trying to optimize it in context. - */ +// This is a deliberate, small cartesian product, so we have manually lifted it to force the +// evaluator to evaluate it in its entirety, rather than trying to optimize it in context. pragma[noinline] private predicate defaultDelegateConversion(RefType fromType, RefType toType) { fromType instanceof DelegateType and toType = any(SystemDelegateClass c).getABaseType*() @@ -489,16 +509,13 @@ private predicate convRefTypeRefType(RefType fromType, RefType toType) { or defaultDelegateConversion(fromType, toType) or - exists(Type t | - convIdentity(fromType, t) or convRefTypeRefType(fromType, t) | + exists(Type t | convIdentity(fromType, t) or convRefTypeRefType(fromType, t) | convIdentity(t, toType) or convVariance(t, toType) ) } -/* - * This is a deliberate, small cartesian product, so we have manually lifted it to force the - * evaluator to evaluate it in its entirety, rather than trying to optimize it in context. - */ +// This is a deliberate, small cartesian product, so we have manually lifted it to force the +// evaluator to evaluate it in its entirety, rather than trying to optimize it in context. pragma[noinline] private predicate defaultArrayConversion(Type fromType, RefType toType) { fromType instanceof ArrayType and toType = any(SystemArrayClass c).getABaseType*() @@ -513,12 +530,10 @@ private predicate convArrayTypeRefType(ArrayType fromType, RefType toType) { fromType.getDimension() = 1 and fromType.getRank() = 1 and argumentType = getIListTypeArgument(ci) and - exists(ArrayElementType elementType | - elementType = fromType.getElementType() | + exists(ArrayElementType elementType | elementType = fromType.getElementType() | convIdentity(elementType, argumentType) or convRefTypeNonNull(elementType, argumentType) - ) - and + ) and toType = ci.getABaseType*() ) } @@ -567,8 +582,7 @@ predicate convBoxing(Type fromType, Type toType) { or convBoxingTypeParameter(fromType, toType) or - exists(Type t | - convBoxing(fromType, t) | + exists(Type t | convBoxing(fromType, t) | convIdentity(t, toType) or convVariance(t, toType) ) @@ -605,13 +619,17 @@ private class SignedIntegralConstantExpr extends Expr { } private predicate convConstantIntExpr(SignedIntegralConstantExpr e, SimpleType toType) { - exists(int n | - n = e.getValue().toInt() | - toType = any(SByteType t | n in [t.minValue() .. t.maxValue()]) or - toType = any(ByteType t | n in [t.minValue() .. t.maxValue()]) or - toType = any(ShortType t | n in [t.minValue() .. t.maxValue()]) or - toType = any(UShortType t | n in [t.minValue() .. t.maxValue()]) or - toType instanceof UIntType and n >= 0 or + exists(int n | n = e.getValue().toInt() | + toType = any(SByteType t | n in [t.minValue() .. t.maxValue()]) + or + toType = any(ByteType t | n in [t.minValue() .. t.maxValue()]) + or + toType = any(ShortType t | n in [t.minValue() .. t.maxValue()]) + or + toType = any(UShortType t | n in [t.minValue() .. t.maxValue()]) + or + toType instanceof UIntType and n >= 0 + or toType instanceof ULongType and n >= 0 ) } @@ -637,8 +655,7 @@ private predicate convBoxingTypeParameter(TypeParameter fromType, Type toType) { private predicate convTypeParameter(TypeParameter fromType, Type toType) { toType = convTypeParameterBase(fromType) or - exists(Type t | - convTypeParameter(fromType, t) | + exists(Type t | convTypeParameter(fromType, t) | convIdentity(t, toType) or convVariance(t, toType) ) @@ -663,8 +680,7 @@ private Type convTypeParameterBase(TypeParameter tp) { private Class effectiveBaseClassCandidate(TypeParameter tp) { not hasPrimaryConstraints(tp) and result instanceof ObjectType or - exists(TypeParameterConstraints tpc | - tpc = tp.getConstraints() | + exists(TypeParameterConstraints tpc | tpc = tp.getConstraints() | tpc.hasValueTypeConstraint() and result instanceof SystemValueTypeClass or result = tpc.getClassConstraint() @@ -677,8 +693,7 @@ private Class effectiveBaseClassCandidate(TypeParameter tp) { /** 10.1.5: Whether type parameter `tp` has primary constraints. */ private predicate hasPrimaryConstraints(TypeParameter tp) { - exists(TypeParameterConstraints tpc | - tpc = tp.getConstraints() | + exists(TypeParameterConstraints tpc | tpc = tp.getConstraints() | exists(tpc.getClassConstraint()) or tpc.hasRefTypeConstraint() @@ -689,8 +704,7 @@ private predicate hasPrimaryConstraints(TypeParameter tp) { /** 10.1.5: The effective interface set of a type parameter `tp` */ private Interface effectiveInterfaceSet(TypeParameter tp) { - exists(TypeParameterConstraints tpc | - tpc = tp.getConstraints() | + exists(TypeParameterConstraints tpc | tpc = tp.getConstraints() | result = tpc.getAnInterfaceConstraint() or result = effectiveInterfaceSet(tpc.getATypeParameterConstraint()) @@ -717,26 +731,25 @@ predicate convConversionOperator(Type fromType, Type toType) { /** 13.1.3.2: Variance conversion. */ private predicate convVariance(ConstructedType fromType, ConstructedType toType) { - /* Semantically equivalent with - * ``` - * ugt = fromType.getUnboundGeneric() - * and - * forex(int i | - * i in [0 .. ugt.getNumberOfTypeParameters() - 1] | - * exists(Type t1, Type t2, TypeParameter tp | - * t1 = getTypeArgument(ugt, fromType, i, tp) and - * t2 = getTypeArgument(ugt, toType, i, tp) | - * convIdentity(t1, t2) - * or - * convRefTypeNonNull(t1, t2) and tp.isOut() - * or - * convRefTypeNonNull(t2, t1) and tp.isIn() - * ) - * ) - * ``` - * but performance is improved by explicitly evaluating the `i`th argument - * only when all preceding arguments are convertible. - */ + // Semantically equivalent with + // ``` + // ugt = fromType.getUnboundGeneric() + // and + // forex(int i | + // i in [0 .. ugt.getNumberOfTypeParameters() - 1] | + // exists(Type t1, Type t2, TypeParameter tp | + // t1 = getTypeArgument(ugt, fromType, i, tp) and + // t2 = getTypeArgument(ugt, toType, i, tp) | + // convIdentity(t1, t2) + // or + // convRefTypeNonNull(t1, t2) and tp.isOut() + // or + // convRefTypeNonNull(t2, t1) and tp.isIn() + // ) + // ) + // ``` + // but performance is improved by explicitly evaluating the `i`th argument + // only when all preceding arguments are convertible. Variance::convVarianceSingle(_, fromType, toType) or exists(UnboundGenericType ugt | @@ -753,18 +766,15 @@ private module Variance { private predicate isVarianceConvertible(ConstructedType ct, int i) { exists(TypeParameter tp, Type t | tp = ct.getUnboundGeneric().getTypeParameter(i) and - t = ct.getTypeArgument(i) | - ( - // Anything that is not a type parameter is potentially convertible - // to/from another type; if the `i`th type parameter is invariant, - // `t` must be strictly identity convertible - not t instanceof TypeParameter - and - (tp.isIn() or tp.isOut() or Identity::convIdentityStrict(t, _)) - ) + t = ct.getTypeArgument(i) + | + // Anything that is not a type parameter is potentially convertible + // to/from another type; if the `i`th type parameter is invariant, + // `t` must be strictly identity convertible + not t instanceof TypeParameter and + (tp.isIn() or tp.isOut() or Identity::convIdentityStrict(t, _)) or - exists(TypeParameter s | - s = t | + exists(TypeParameter s | s = t | // A type parameter with implicit reference conversion exists(convTypeParameterBase(s)) and s.isRefType() and tp.isOut() or @@ -775,9 +785,7 @@ private module Variance { } private class VarianceConvertibleConstructedType extends ConstructedType { - VarianceConvertibleConstructedType() { - isVarianceConvertible(this, _) - } + VarianceConvertibleConstructedType() { isVarianceConvertible(this, _) } } /** @@ -786,22 +794,20 @@ private module Variance { */ private int getTypeArgumentCount(UnboundGenericType ugt, int i) { result = strictcount(Type arg | - exists(VarianceConvertibleConstructedType ct | - ct.getUnboundGeneric() = ugt | - arg = ct.getTypeArgument(i) + exists(VarianceConvertibleConstructedType ct | ct.getUnboundGeneric() = ugt | + arg = ct.getTypeArgument(i) + ) ) - ) } private int rnk(UnboundGenericType ugt, int i) { - result = rank[i + 1](int j, int k | - j = getTypeArgumentCount(ugt, k) | - k order by j, k - ) + result = rank[i + 1](int j, int k | j = getTypeArgumentCount(ugt, k) | k order by j, k) } /** Gets the 'i'th type argument, ranked by size, of constructed type `t`. */ - private Type getTypeArgumentRanked(UnboundGenericType ugt, VarianceConvertibleConstructedType t, int i, TypeParameter tp) { + private Type getTypeArgumentRanked( + UnboundGenericType ugt, VarianceConvertibleConstructedType t, int i, TypeParameter tp + ) { result = getTypeArgument(ugt, t, rnk(ugt, i), tp) } @@ -825,19 +831,25 @@ private module Variance { toType = getATypeArgumentRankedIn(i) } - private newtype TVariance = TNone() or TIn() or TOut() + private newtype TVariance = + TNone() or + TIn() or + TOut() /** * Holds if `fromTypeArgument` is convertible to `toTypeArgument`, with variance * `v`, and both types are the `i`th type argument in _some_ constructed type. */ pragma[nomagic] - private predicate convTypeArguments(TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i, TVariance v) { + private predicate convTypeArguments( + TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i, TVariance v + ) { exists(int j | fromTypeArgument = getTypeArgumentRanked(_, _, i, _) and toTypeArgument = getTypeArgumentRanked(_, _, j, _) and - i <= j and j <= i - | + i <= j and + j <= i + | convIdentity(fromTypeArgument, toTypeArgument) and v = TNone() or @@ -850,9 +862,12 @@ private module Variance { } pragma[nomagic] - private predicate convTypeArgumentsSomeUnbound(UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i) { + private predicate convTypeArgumentsSomeUnbound( + UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i + ) { exists(TypeParameter tp, TVariance v | - convTypeArguments(fromTypeArgument, toTypeArgument, i, v) | + convTypeArguments(fromTypeArgument, toTypeArgument, i, v) + | fromTypeArgument = getTypeArgumentRanked(ugt, _, i, tp) and (v = TIn() implies tp.isIn()) and (v = TOut() implies tp.isOut()) @@ -865,13 +880,18 @@ private module Variance { * based on unbound generic type `ugt`. */ pragma[noinline] - private predicate convTypeArgumentsSameUnbound(UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i) { + private predicate convTypeArgumentsSameUnbound( + UnboundGenericType ugt, TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i + ) { convTypeArgumentsSomeUnbound(ugt, fromTypeArgument, toTypeArgument, i) and toTypeArgument = getTypeArgumentRanked(ugt, _, i, _) } pragma[nomagic] - private predicate convVarianceSingle0(UnboundGenericType ugt, VarianceConvertibleConstructedType toType, TypeArgument fromTypeArgument, TypeArgument toTypeArgument) { + private predicate convVarianceSingle0( + UnboundGenericType ugt, VarianceConvertibleConstructedType toType, + TypeArgument fromTypeArgument, TypeArgument toTypeArgument + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, 0) and toTypeArgument = getTypeArgumentRanked(ugt, toType, 0, _) and ugt.getNumberOfTypeParameters() = 1 @@ -881,22 +901,32 @@ private module Variance { * Holds if the type arguments of types `fromType` and `toType` are variance * convertible, and the number of type arguments is 1. */ - predicate convVarianceSingle(UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, VarianceConvertibleConstructedType toType) { + predicate convVarianceSingle( + UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, + VarianceConvertibleConstructedType toType + ) { exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument | - convVarianceSingle0(ugt, toType, fromTypeArgument, toTypeArgument) | + convVarianceSingle0(ugt, toType, fromTypeArgument, toTypeArgument) + | fromTypeArgument = getTypeArgumentRanked(ugt, fromType, 0, _) ) } pragma[nomagic] - private predicate convVarianceMultiple01Aux0(UnboundGenericType ugt, VarianceConvertibleConstructedType toType, TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument toTypeArgument1) { + private predicate convVarianceMultiple01Aux0( + UnboundGenericType ugt, VarianceConvertibleConstructedType toType, + TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument toTypeArgument1 + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument0, toTypeArgument0, 0) and toTypeArgument0 = getTypeArgumentRanked(ugt, toType, 0, _) and toTypeArgument1 = getTypeArgumentRanked(ugt, toType, 1, _) } pragma[nomagic] - private predicate convVarianceMultiple01Aux1(UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, TypeArgument fromTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1) { + private predicate convVarianceMultiple01Aux1( + UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, + TypeArgument fromTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1 + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument1, toTypeArgument1, 1) and fromTypeArgument0 = getTypeArgumentRanked(ugt, fromType, 0, _) and fromTypeArgument1 = getTypeArgumentRanked(ugt, fromType, 1, _) @@ -906,23 +936,38 @@ private module Variance { * Holds if the first two ranked type arguments of types `fromType` and `toType` * are variance convertible. */ - private predicate convVarianceMultiple01(UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, VarianceConvertibleConstructedType toType) { - exists(TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1 | - convVarianceMultiple01Aux0(ugt, toType, fromTypeArgument0, toTypeArgument0, toTypeArgument1) | - convVarianceMultiple01Aux1(ugt, fromType, fromTypeArgument0, fromTypeArgument1, toTypeArgument1) + private predicate convVarianceMultiple01( + UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, + VarianceConvertibleConstructedType toType + ) { + exists( + TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument fromTypeArgument1, + TypeArgument toTypeArgument1 + | + convVarianceMultiple01Aux0(ugt, toType, fromTypeArgument0, toTypeArgument0, toTypeArgument1) + | + convVarianceMultiple01Aux1(ugt, fromType, fromTypeArgument0, fromTypeArgument1, + toTypeArgument1) ) } pragma[nomagic] - private predicate convVarianceMultiple2Aux(UnboundGenericType ugt, VarianceConvertibleConstructedType toType, int i, TypeArgument fromTypeArgument, TypeArgument toTypeArgument) { + private predicate convVarianceMultiple2Aux( + UnboundGenericType ugt, VarianceConvertibleConstructedType toType, int i, + TypeArgument fromTypeArgument, TypeArgument toTypeArgument + ) { convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, i) and toTypeArgument = getTypeArgumentRanked(ugt, toType, i, _) and i >= 2 } - private predicate convVarianceMultiple2(UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, VarianceConvertibleConstructedType toType, int i) { + private predicate convVarianceMultiple2( + UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, + VarianceConvertibleConstructedType toType, int i + ) { exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument | - convVarianceMultiple2Aux(ugt, toType, i, fromTypeArgument, toTypeArgument) | + convVarianceMultiple2Aux(ugt, toType, i, fromTypeArgument, toTypeArgument) + | fromTypeArgument = getTypeArgumentRanked(ugt, fromType, i, _) ) } @@ -932,7 +977,10 @@ private module Variance { * `fromType` and `toType` are variance convertible. */ pragma[nomagic] - predicate convVarianceMultiple(UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, VarianceConvertibleConstructedType toType, int i) { + predicate convVarianceMultiple( + UnboundGenericType ugt, VarianceConvertibleConstructedType fromType, + VarianceConvertibleConstructedType toType, int i + ) { convVarianceMultiple01(ugt, fromType, toType) and i = 1 or convVarianceMultiple(ugt, fromType, toType, i - 1) and diff --git a/csharp/ql/src/semmle/code/csharp/Element.qll b/csharp/ql/src/semmle/code/csharp/Element.qll index 8bcff46054f..1adf83d93b9 100644 --- a/csharp/ql/src/semmle/code/csharp/Element.qll +++ b/csharp/ql/src/semmle/code/csharp/Element.qll @@ -48,15 +48,11 @@ class Element extends DotNet::Element, @element { /** Gets the number of children of this element. */ pragma[nomagic] - int getNumberOfChildren() { - result = count(int i | exists(this.getChild(i))) - } + int getNumberOfChildren() { result = count(int i | exists(this.getChild(i))) } /** * Gets the index of this element among its parent's * other children (zero-based). */ - int getIndex() { - exists(Element parent | parent.getChild(result) = this) - } + int getIndex() { exists(Element parent | parent.getChild(result) = this) } } diff --git a/csharp/ql/src/semmle/code/csharp/Enclosing.qll b/csharp/ql/src/semmle/code/csharp/Enclosing.qll index c7bb6c34f3c..ab106421196 100644 --- a/csharp/ql/src/semmle/code/csharp/Enclosing.qll +++ b/csharp/ql/src/semmle/code/csharp/Enclosing.qll @@ -18,20 +18,20 @@ private import semmle.code.csharp.ExprOrStmtParent /** * INTERNAL: Do not use. */ -cached module Internal { +cached +module Internal { /** * INTERNAL: Do not use. * * Holds if `c` is the enclosing callable of statement `s`. */ - cached predicate enclosingCallable(Stmt s, Callable c) { - /* - * Compute the enclosing callable for a statement. This walks up through - * enclosing statements until it hits a callable. It's unambiguous, since - * if a statement has no parent statement, it's either the method body - * or the body of an anonymous function declaration, in each of which cases the - * non-statement parent is in fact the enclosing callable. - */ + cached + predicate enclosingCallable(Stmt s, Callable c) { + // Compute the enclosing callable for a statement. This walks up through + // enclosing statements until it hits a callable. It's unambiguous, since + // if a statement has no parent statement, it's either the method body + // or the body of an anonymous function declaration, in each of which cases the + // non-statement parent is in fact the enclosing callable. c.getAChildStmt+() = s } @@ -45,21 +45,19 @@ cached module Internal { * * Holds if `s` is the enclosing statement of expression `e`. */ - cached predicate enclosingStmt(Expr e, Stmt s) { - /* - * Compute the enclosing statement for an expression. Note that this need - * not exist, since expressions can occur in contexts where they have no - * enclosing statement (examples include field initialisers, both inline - * and explicit on constructor definitions, and annotation arguments). - */ + cached + predicate enclosingStmt(Expr e, Stmt s) { + // Compute the enclosing statement for an expression. Note that this need + // not exist, since expressions can occur in contexts where they have no + // enclosing statement (examples include field initialisers, both inline + // and explicit on constructor definitions, and annotation arguments). getAChildExpr+(s) = e } private predicate childExprOfCallable(Callable parent, Expr child) { child = getAChildExpr(parent) or - exists(Expr mid | - childExprOfCallable(parent, mid) | + exists(Expr mid | childExprOfCallable(parent, mid) | not mid instanceof Callable and child = getAChildExpr(mid) ) @@ -70,14 +68,13 @@ cached module Internal { * * Holds if `c` is the enclosing callable of expression `e`. */ - cached predicate exprEnclosingCallable(Expr e, Callable c) { - /* - * Compute the enclosing callable of an expression. Note that expressions in - * lambda functions should have the lambdas as enclosing callables, and their - * enclosing statement may be the same as the enclosing statement of the - * lambda; thus, it is *not* safe to go up to the enclosing statement and - * take its own enclosing callable. - */ + cached + predicate exprEnclosingCallable(Expr e, Callable c) { + // Compute the enclosing callable of an expression. Note that expressions in + // lambda functions should have the lambdas as enclosing callables, and their + // enclosing statement may be the same as the enclosing statement of the + // lambda; thus, it is *not* safe to go up to the enclosing statement and + // take its own enclosing callable. childExprOfCallable(c, e) or not childExprOfCallable(_, e) and diff --git a/csharp/ql/src/semmle/code/csharp/Event.qll b/csharp/ql/src/semmle/code/csharp/Event.qll index 459b6732c4f..38f89428b6f 100644 --- a/csharp/ql/src/semmle/code/csharp/Event.qll +++ b/csharp/ql/src/semmle/code/csharp/Event.qll @@ -16,12 +16,11 @@ import Type * ``` */ class Event extends DeclarationWithAccessors, @event { + override string getName() { events(this, result, _, _, _) } - override string getName() { events(this,result,_,_,_) } + override ValueOrRefType getDeclaringType() { events(this, _, result, _, _) } - override ValueOrRefType getDeclaringType() { events(this,_,result,_,_) } - - override DelegateType getType() { events(this,_,_,getTypeRef(result),_) } + override DelegateType getType() { events(this, _, _, getTypeRef(result), _) } /** Gets an `add` or `remove` accessor of this event, if any. */ EventAccessor getAnEventAccessor() { result.getDeclaration() = this } @@ -43,23 +42,15 @@ class Event extends DeclarationWithAccessors, @event { not this.getAnEventAccessor().hasBody() } - override Event getSourceDeclaration() { events(this,_,_,_,result) } + override Event getSourceDeclaration() { events(this, _, _, _, result) } - override Event getOverridee() { - result = DeclarationWithAccessors.super.getOverridee() - } + override Event getOverridee() { result = DeclarationWithAccessors.super.getOverridee() } - override Event getAnOverrider() { - result = DeclarationWithAccessors.super.getAnOverrider() - } + override Event getAnOverrider() { result = DeclarationWithAccessors.super.getAnOverrider() } - override Event getImplementee() { - result = DeclarationWithAccessors.super.getImplementee() - } + override Event getImplementee() { result = DeclarationWithAccessors.super.getImplementee() } - override Event getAnImplementor() { - result = DeclarationWithAccessors.super.getAnImplementor() - } + override Event getAnImplementor() { result = DeclarationWithAccessors.super.getAnImplementor() } override Event getAnUltimateImplementee() { result = DeclarationWithAccessors.super.getAnUltimateImplementee() @@ -69,7 +60,7 @@ class Event extends DeclarationWithAccessors, @event { result = DeclarationWithAccessors.super.getAnUltimateImplementor() } - override Location getALocation() { event_location(this,result) } + override Location getALocation() { event_location(this, result) } } /** @@ -92,13 +83,13 @@ class EventAccessor extends Accessor, @event_accessor { result instanceof VoidType } - override string getAssemblyName() { event_accessors(this,_,result,_,_) } + override string getAssemblyName() { event_accessors(this, _, result, _, _) } - override EventAccessor getSourceDeclaration() { event_accessors(this,_,_,_,result) } + override EventAccessor getSourceDeclaration() { event_accessors(this, _, _, _, result) } - override Event getDeclaration() { event_accessors(this,_,_,result,_) } + override Event getDeclaration() { event_accessors(this, _, _, result, _) } - override Location getALocation() { event_accessor_location(this,result) } + override Location getALocation() { event_accessor_location(this, result) } } /** @@ -132,5 +123,5 @@ class AddEventAccessor extends EventAccessor, @add_event_accessor { * ``` */ class RemoveEventAccessor extends EventAccessor, @remove_event_accessor { - override string getName() { result = "remove" + "_" + getDeclaration().getName() } + override string getName() { result = "remove" + "_" + getDeclaration().getName() } } diff --git a/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll b/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll index 42e81853a21..73dc5432b38 100644 --- a/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll +++ b/csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll @@ -3,6 +3,7 @@ * * Provides logic for calculating the child relation on expressions and statements. */ + import csharp /** @@ -14,9 +15,7 @@ import csharp predicate expr_parent_top_level_adjusted(Expr child, int i, @top_level_exprorstmt_parent parent) { expr_parent_top_level(child, i, parent) or - parent = any(Getter g | - expr_parent_top_level(child, i, g.getDeclaration()) - ) + parent = any(Getter g | expr_parent_top_level(child, i, g.getDeclaration())) } /** @@ -51,12 +50,12 @@ predicate expr_parent_top_level_adjusted(Expr child, int i, @top_level_exprorstm * ``` */ private predicate expr_parent_adjusted(Expr child, int i, ControlFlowElement parent) { - exists(AssignExpr ae | - ae = parent.(AssignOperation).getExpandedAssignment() | + exists(AssignExpr ae | ae = parent.(AssignOperation).getExpandedAssignment() | i = 0 and exists(Expr right | // right = `x + y` - expr_parent(right, 0, ae) | + expr_parent(right, 0, ae) + | expr_parent(child, 1, right) ) or @@ -86,9 +85,7 @@ class ExprOrStmtParent extends Element, @exprorstmt_parent { } /** Gets a child expression of this element, if any. */ - final Expr getAChildExpr() { - result = this.getChildExpr(_) - } + final Expr getAChildExpr() { result = this.getChildExpr(_) } /** Gets the `i`th child statement of this element (zero-based). */ final Stmt getChildStmt(int i) { @@ -97,9 +94,7 @@ class ExprOrStmtParent extends Element, @exprorstmt_parent { } /** Gets a child statement of this element, if any. */ - final Stmt getAChildStmt() { - result = this.getChildStmt(_) - } + final Stmt getAChildStmt() { result = this.getChildStmt(_) } } /** @@ -108,19 +103,13 @@ class ExprOrStmtParent extends Element, @exprorstmt_parent { * An element that can have a child top-level expression. */ class TopLevelExprParent extends Element, @top_level_expr_parent { - final override Expr getChild(int i) { - result = this.getChildExpr(i) - } + final override Expr getChild(int i) { result = this.getChildExpr(i) } /** Gets the `i`th child expression of this element (zero-based). */ - final Expr getChildExpr(int i) { - result = getTopLevelChild(this, i) - } + final Expr getChildExpr(int i) { result = getTopLevelChild(this, i) } /** Gets a child expression of this element, if any. */ - final Expr getAChildExpr() { - result = this.getChildExpr(_) - } + final Expr getAChildExpr() { result = this.getChildExpr(_) } } /** @@ -159,8 +148,7 @@ class MultiImplementationsParent extends ExprOrStmtParent { MultiImplementationsParent() { exists(int i | strictcount(File f | - exists(ControlFlowElement implementation, Location l | - f = l.getFile() | + exists(ControlFlowElement implementation, Location l | f = l.getFile() | stmt_parent_top_level(implementation, i, this) and stmt_location(implementation, l) or @@ -179,8 +167,7 @@ class MultiImplementationsParent extends ExprOrStmtParent { * element. */ private File getAnImplementation(int i, ControlFlowElement cfe) { - exists(Location l | - result = l.getFile() | + exists(Location l | result = l.getFile() | stmt_parent_top_level(cfe, i, this) and stmt_location(cfe, l) or @@ -231,8 +218,9 @@ class MultiImplementationsParent extends ExprOrStmtParent { File getBestFile() { exists(ValueOrRefType t | result = max(this.getAnImplementationFileInTopLevelType(_, t) as file - order by getImplementationSize(t, file), file.toString() - ) + order by + getImplementationSize(t, file), file.toString() + ) ) } @@ -242,8 +230,7 @@ class MultiImplementationsParent extends ExprOrStmtParent { * be the actual run-time implementation. */ ControlFlowElement getBestChild(int i) { - exists(File f, ValueOrRefType t | - f = getBestFile() | + exists(File f, ValueOrRefType t | f = getBestFile() | f = this.getAnImplementationInTopLevelType(i, result, t) ) } @@ -255,11 +242,9 @@ class MultiImplementationsParent extends ExprOrStmtParent { * Holds if accessor `a` has an auto-implementation in file `f`. */ predicate hasAccessorAutoImplementation(Accessor a, File f) { - exists(SourceLocation sl | - sl = a.getALocation() | + exists(SourceLocation sl | sl = a.getALocation() | f = sl.getFile() and - not exists(ControlFlowElement cfe, Location l | - sl.getFile() = l.getFile() | + not exists(ControlFlowElement cfe, Location l | sl.getFile() = l.getFile() | stmt_parent_top_level(cfe, _, a) and stmt_location(cfe, l) or @@ -293,15 +278,9 @@ private ValueOrRefType getDeclaringType(Declaration d) { or fields(d, _, _, result, _, _) or - exists(DeclarationWithAccessors decl | - d = decl.getAnAccessor() | - result = getDeclaringType(decl) - ) + exists(DeclarationWithAccessors decl | d = decl.getAnAccessor() | result = getDeclaringType(decl)) or - exists(Parameterizable p | - params(d, _, _, _, _, p, _) | - result = getDeclaringType(p) - ) + exists(Parameterizable p | params(d, _, _, _, _, p, _) | result = getDeclaringType(p)) } private ControlFlowElement getAChild(ControlFlowElement cfe) { @@ -311,42 +290,45 @@ private ControlFlowElement getAChild(ControlFlowElement cfe) { private int getImplementationSize0(ValueOrRefType t, File f) { result = strictcount(ControlFlowElement cfe | - exists(MultiImplementationsParent p, ControlFlowElement child | - cfe = getAChild*(child) and - not cfe = getAChild*(any(ThrowElement te)) | - f = p.getAnImplementationInTopLevelType(_, child, t) - or - // Merge stats for partial implementations belonging to the same folder - t.isPartial() and - f = p.getAnImplementationInTopLevelType(_, _, t) and - exists(File fOther, MultiImplementationsParent pOther | - f.getParentContainer() = fOther.getParentContainer() | - fOther = pOther.getAnImplementationInTopLevelType(_, child, t) + exists(MultiImplementationsParent p, ControlFlowElement child | + cfe = getAChild*(child) and + not cfe = getAChild*(any(ThrowElement te)) + | + f = p.getAnImplementationInTopLevelType(_, child, t) + or + // Merge stats for partial implementations belonging to the same folder + t.isPartial() and + f = p.getAnImplementationInTopLevelType(_, _, t) and + exists(File fOther, MultiImplementationsParent pOther | + f.getParentContainer() = fOther.getParentContainer() + | + fOther = pOther.getAnImplementationInTopLevelType(_, child, t) + ) ) ) - ) } private int getImplementationSize1(ValueOrRefType t, File f) { result = strictsum(MultiImplementationsParent p, int c | - // Count each auto-implemented accessor as size 4 (getter) or 5 (setter) - f = p.getAnAutoImplementationFileInTopLevelType(t) and - if p instanceof Getter then c = 4 else c = 5 | - c - ) + // Count each auto-implemented accessor as size 4 (getter) or 5 (setter) + f = p.getAnAutoImplementationFileInTopLevelType(t) and + if p instanceof Getter then c = 4 else c = 5 + | + c + ) } private int getImplementationSize(ValueOrRefType t, File f) { - if exists(getImplementationSize0(t, f)) then - if exists(getImplementationSize1(t, f)) then - result = getImplementationSize0(t, f) + getImplementationSize1(t, f) - else - result = getImplementationSize0(t, f) - else - result = getImplementationSize1(t, f) + if exists(getImplementationSize0(t, f)) + then + if exists(getImplementationSize1(t, f)) + then result = getImplementationSize0(t, f) + getImplementationSize1(t, f) + else result = getImplementationSize0(t, f) + else result = getImplementationSize1(t, f) } -cached module ExprOrStmtParentCached { +cached +module ExprOrStmtParentCached { cached ControlFlowElement getTopLevelChild(ExprOrStmtParent p, int i) { result = p.(MultiImplementationsParent).getBestChild(i) @@ -366,7 +348,8 @@ cached module ExprOrStmtParentCached { predicate mustHaveLocationInFile(Declaration d, File f) { exists(MultiImplementationsParent p, ValueOrRefType t | t = getTopLevelDeclaringType(p) and - f = p.getBestFile() | + f = p.getBestFile() + | t = getTopLevelDeclaringType(d) or d = t or d = p ) } @@ -385,17 +368,13 @@ cached module ExprOrStmtParentCached { result = e.getALocation().(SourceLocation) and (mustHaveLocationInFile(e, _) implies mustHaveLocationInFile(e, result.getFile())) or - ( - hasNoSourceLocation(e) - and - result = min(Location l | l = e.getALocation() | l order by l.getFile().toString()) - ) + hasNoSourceLocation(e) and + result = min(Location l | l = e.getALocation() | l order by l.getFile().toString()) } cached string getURL(Element e) { - exists(Location l, string path, int a, int b, int c, int d | - l = bestLocation(e) | + exists(Location l, string path, int a, int b, int c, int d | l = bestLocation(e) | l.hasLocationInfo(path, a, b, c, d) and toUrl(path, a, b, c, d, result) ) diff --git a/csharp/ql/src/semmle/code/csharp/File.qll b/csharp/ql/src/semmle/code/csharp/File.qll index 797b171d1ce..1d22de35548 100644 --- a/csharp/ql/src/semmle/code/csharp/File.qll +++ b/csharp/ql/src/semmle/code/csharp/File.qll @@ -46,8 +46,9 @@ class Container extends @container { * if the root folder is not a reflexive, transitive parent of this container. */ string getRelativePath() { - exists (string absPath, string pref | - absPath = getAbsolutePath() and sourceLocationPrefix(pref) | + exists(string absPath, string pref | + absPath = getAbsolutePath() and sourceLocationPrefix(pref) + | absPath = pref and result = "" or absPath = pref.regexpReplaceAll("/$", "") + "/" + result and @@ -99,9 +100,7 @@ class Container extends @container { * "/tmp/x.tar.gz""gz" * */ - string getExtension() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) - } + string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -120,24 +119,16 @@ class Container extends @container { * "/tmp/x.tar.gz""x.tar" * */ - string getStem() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) - } + string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } /** Gets the parent container of this file or folder, if any. */ - Container getParentContainer() { - containerparent(result, this) - } + Container getParentContainer() { containerparent(result, this) } /** Gets a file or sub-folder in this container. */ - Container getAChildContainer() { - this = result.getParentContainer() - } + Container getAChildContainer() { this = result.getParentContainer() } /** Gets a file in this container. */ - File getAFile() { - result = getAChildContainer() - } + File getAFile() { result = getAChildContainer() } /** Gets the file in this container that has the given `baseName`, if any. */ File getFile(string baseName) { @@ -146,9 +137,7 @@ class Container extends @container { } /** Gets a sub-folder in this container. */ - Folder getAFolder() { - result = getAChildContainer() - } + Folder getAFolder() { result = getAChildContainer() } /** Gets the sub-folder in this container that has the given `baseName`, if any. */ Folder getFolder(string baseName) { @@ -170,60 +159,40 @@ class Container extends @container { } /** Gets a sub-folder contained in this container. */ - Folder getASubFolder() { - result = getAChildContainer() - } + Folder getASubFolder() { result = getAChildContainer() } /** * Gets a textual representation of the path of this container. * * This is the absolute path of the container. */ - string toString() { - result = getAbsolutePath() - } + string toString() { result = getAbsolutePath() } } /** A folder. */ class Folder extends Container, @folder { - override string getAbsolutePath() { - folders(this, result, _) - } + override string getAbsolutePath() { folders(this, result, _) } - override string getURL() { - result = "folder://" + getAbsolutePath() - } + override string getURL() { result = "folder://" + getAbsolutePath() } } /** A file. */ class File extends Container, @file { - override string getAbsolutePath() { - files(this, result, _, _, _) - } + override string getAbsolutePath() { files(this, result, _, _, _) } /** Gets the number of lines in this file. */ - int getNumberOfLines() { - numlines(this, result, _, _) - } + int getNumberOfLines() { numlines(this, result, _, _) } /** Gets the number of lines containing code in this file. */ - int getNumberOfLinesOfCode() { - numlines(this, _, result, _) - } + int getNumberOfLinesOfCode() { numlines(this, _, result, _) } /** Gets the number of lines containing comments in this file. */ - int getNumberOfLinesOfComments() { - numlines(this, _, _, result) - } + int getNumberOfLinesOfComments() { numlines(this, _, _, result) } - override string getURL() { - result = "file://" + this.getAbsolutePath() + ":0:0:0:0" - } + override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } /** Holds if this file contains source code. */ - predicate fromSource() { - this.getNumberOfLinesOfCode() > 0 - } + predicate fromSource() { this.getNumberOfLinesOfCode() > 0 } /** Holds if this file is a library. */ predicate fromLibrary() { @@ -236,20 +205,15 @@ 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() { file_extraction_mode(this, 2) } } /** * A source file. */ 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() { file_extraction_mode(this, 1) } } diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index 1c9fc33765a..83fb04b2368 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -37,13 +37,9 @@ class Generic extends DotNet::Generic, Declaration, @generic { class UnboundGeneric extends DotNet::UnboundGeneric, Generic { UnboundGeneric() { is_generic(this) } - override TypeParameter getTypeParameter(int n) { - type_parameters(result, n, this, _) - } + override TypeParameter getTypeParameter(int n) { type_parameters(result, n, this, _) } - override ConstructedGeneric getAConstructedGeneric() { - result.getUnboundGeneric() = this - } + override ConstructedGeneric getAConstructedGeneric() { result.getUnboundGeneric() = this } override TypeParameter getATypeParameter() { result = DotNet::UnboundGeneric.super.getATypeParameter() @@ -59,24 +55,20 @@ class UnboundGeneric extends DotNet::UnboundGeneric, Generic { class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic { ConstructedGeneric() { is_constructed(this) } - override UnboundGeneric getUnboundGeneric() { - constructed_generic(this, result) - } + override UnboundGeneric getUnboundGeneric() { constructed_generic(this, result) } override UnboundGeneric getSourceDeclaration() { result = getUnboundGeneric().getSourceDeclaration() } override int getNumberOfTypeArguments() { - // getTypeArgument() could fail if the type does not exist in the database - result = count(int i | type_arguments(_, i, this)) + // getTypeArgument() could fail if the type does not exist in the database + result = count(int i | type_arguments(_, i, this)) } override Type getTypeArgument(int i) { none() } - override Type getATypeArgument() { - result=getTypeArgument(_) - } + override Type getATypeArgument() { result = getTypeArgument(_) } } /** @@ -105,13 +97,11 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { * arguments being the corresponding type parameter. */ ConstructedType getInstanceType() { - result = this.getAConstructedGeneric() - and forall(TypeParameter tp, int i | tp = this.getTypeParameter(i) | tp = result.getTypeArgument(i)) + result = this.getAConstructedGeneric() and + forall(TypeParameter tp, int i | tp = this.getTypeParameter(i) | tp = result.getTypeArgument(i)) } - override Location getALocation() { - type_location(this, result) - } + override Location getALocation() { type_location(this, result) } /** Gets the name of this generic type without the `<...>` brackets. */ string getNameWithoutBrackets() { @@ -134,17 +124,14 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric { */ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter { /** Gets the constraints on this type parameter, if any. */ - TypeParameterConstraints getConstraints() { - result.getTypeParameter() = this - } + TypeParameterConstraints getConstraints() { result.getTypeParameter() = this } /** * Holds if this type parameter is guaranteed to always be instantiated * to a reference type. */ predicate isRefType() { - exists(TypeParameterConstraints tpc | - tpc = getConstraints() | + exists(TypeParameterConstraints tpc | tpc = getConstraints() | tpc.hasRefTypeConstraint() or exists(tpc.getClassConstraint()) or tpc.getATypeParameterConstraint().isRefType() @@ -157,50 +144,45 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter { * to a value type. */ predicate isValueType() { - exists(TypeParameterConstraints tpc | - tpc = getConstraints() | + exists(TypeParameterConstraints tpc | tpc = getConstraints() | tpc.hasValueTypeConstraint() or tpc.getATypeParameterConstraint().isValueType() ) } /** Holds if this type parameter is contravariant. */ - predicate isIn() { - type_parameters(this, _, _, 2) - } + predicate isIn() { type_parameters(this, _, _, 2) } /** Holds if this type parameter is covariant. */ - predicate isOut() { - type_parameters(this, _, _, 1) - } + predicate isOut() { type_parameters(this, _, _, 1) } /** Gets a type that was supplied for this parameter. */ - Type getASuppliedType() - { - /* A type parameter either comes from the source declaration - or from a partially constructed generic. - - When from a source declaration, return type arguments from all ConstructedGenerics, - and when from a partially constructed UnboundGeneric, return type arguments from - directly ConstructedGenerics. - - e.g. - - class A { class B { } } - - A.B is the UnboundGenericClass source declaration, - A.B is a partially constructed UnboundGenericClass and - A.B is a ConstructedGenericClass. - */ + Type getASuppliedType() { + // A type parameter either comes from the source declaration + // or from a partially constructed generic. + // + // When from a source declaration, return type arguments from all ConstructedGenerics, + // and when from a partially constructed UnboundGeneric, return type arguments from + // directly ConstructedGenerics. + // + // For example: + // + // class A { class B { } } + // + // A.B is the UnboundGenericClass source declaration, + // A.B is a partially constructed UnboundGenericClass and + // A.B is a ConstructedGenericClass. exists(ConstructedGeneric c, UnboundGeneric u, int tpi | this = u.getTypeParameter(tpi) and (u = c.getUnboundGeneric() or u = c.getSourceDeclaration()) and - result = c.getTypeArgument(tpi) ) + result = c.getTypeArgument(tpi) + ) } /** Gets a non-type-parameter type that was transitively supplied for this parameter. */ Type getAnUltimatelySuppliedType() { - result = getASuppliedType() and not result instanceof TypeParameter or + result = getASuppliedType() and not result instanceof TypeParameter + or result = getASuppliedType().(TypeParameter).getAnUltimatelySuppliedType() } @@ -222,7 +204,6 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter { * ``` */ class TypeParameterConstraints extends Element, @type_parameter_constraints { - /** Gets a specific interface constraint (if any). */ Interface getAnInterfaceConstraint() { specific_type_parameter_constraints(this, getTypeRef(result)) @@ -234,38 +215,24 @@ class TypeParameterConstraints extends Element, @type_parameter_constraints { } /** Gets the specific class constraint (if any). */ - Class getClassConstraint() { - specific_type_parameter_constraints(this, getTypeRef(result)) - } + Class getClassConstraint() { specific_type_parameter_constraints(this, getTypeRef(result)) } - override Location getALocation() { - type_parameter_constraints_location(this, result) - } + override Location getALocation() { type_parameter_constraints_location(this, result) } /** Gets the type parameter to which these constraints apply. */ - TypeParameter getTypeParameter() { - type_parameter_constraints(this, result) - } + TypeParameter getTypeParameter() { type_parameter_constraints(this, result) } /** Holds if these constraints include a constructor constraint. */ - predicate hasConstructorConstraint() { - general_type_parameter_constraints(this, 3) - } + predicate hasConstructorConstraint() { general_type_parameter_constraints(this, 3) } /** Holds if these constraints include a general reference type constraint. */ - predicate hasRefTypeConstraint() { - general_type_parameter_constraints(this, 1) - } + predicate hasRefTypeConstraint() { general_type_parameter_constraints(this, 1) } /** Holds if these constraints include a general value type constraint. */ - predicate hasValueTypeConstraint() { - general_type_parameter_constraints(this, 2) - } + predicate hasValueTypeConstraint() { general_type_parameter_constraints(this, 2) } /** Gets a textual representation of these constraints. */ - override string toString() { - result = "where " + this.getTypeParameter().toString() + ": ..." - } + override string toString() { result = "where " + this.getTypeParameter().toString() + ": ..." } } /** @@ -364,7 +331,8 @@ class UnboundGenericDelegateType extends DelegateType, UnboundGenericType { } override string toStringWithTypes() { - result = getNameWithoutBrackets() + "<" + this.typeParametersToString() + ">(" + parameterTypesToString() + ")" + result = getNameWithoutBrackets() + "<" + this.typeParametersToString() + ">(" + + parameterTypesToString() + ")" } } @@ -384,17 +352,11 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { result = ConstructedGeneric.super.getSourceDeclaration() } - override Location getALocation() { - result = this.getSourceDeclaration().getALocation() - } + override Location getALocation() { result = this.getSourceDeclaration().getALocation() } - override Type getTypeArgument(int n) { - type_arguments(getTypeRef(result), n, getTypeRef(this)) - } + override Type getTypeArgument(int n) { type_arguments(getTypeRef(result), n, getTypeRef(this)) } - override UnboundGenericType getUnboundGeneric() { - constructed_generic(this, getTypeRef(result)) - } + override UnboundGenericType getUnboundGeneric() { constructed_generic(this, getTypeRef(result)) } override string toStringWithTypes() { result = getUnboundGeneric().getNameWithoutBrackets() + "<" + this.typeArgumentsToString() + ">" @@ -516,7 +478,8 @@ class UnboundGenericMethod extends Method, UnboundGeneric { } override string toStringWithTypes() { - result = getName() + "<" + this.typeParametersToString() + ">" + "(" + parameterTypesToString() + ")" + result = getName() + "<" + this.typeParametersToString() + ">" + "(" + parameterTypesToString() + + ")" } } @@ -539,20 +502,15 @@ class UnboundGenericMethod extends Method, UnboundGeneric { * corresponds to `UnboundGenericType`. */ class ConstructedMethod extends Method, ConstructedGeneric { - override Location getALocation() { - result = this.getSourceDeclaration().getALocation() - } + override Location getALocation() { result = this.getSourceDeclaration().getALocation() } - override Type getTypeArgument(int n) { - type_arguments(getTypeRef(result), n, this) - } + override Type getTypeArgument(int n) { type_arguments(getTypeRef(result), n, this) } - override UnboundGenericMethod getUnboundGeneric() { - constructed_generic(this, result) - } + override UnboundGenericMethod getUnboundGeneric() { constructed_generic(this, result) } override string toStringWithTypes() { - result = getName() + "<" + this.typeArgumentsToString() + ">" + "(" + parameterTypesToString() + ")" + result = getName() + "<" + this.typeArgumentsToString() + ">" + "(" + parameterTypesToString() + + ")" } override UnboundGenericMethod getSourceDeclaration() { @@ -571,8 +529,7 @@ class ConstructedMethod extends Method, ConstructedGeneric { * } * ``` */ -class UnboundLocalFunction extends LocalFunction, UnboundGeneric -{ +class UnboundLocalFunction extends LocalFunction, UnboundGeneric { override ConstructedLocalFunction getAConstructedGeneric() { result = UnboundGeneric.super.getAConstructedGeneric() } @@ -591,10 +548,9 @@ class UnboundLocalFunction extends LocalFunction, UnboundGeneric * } * ``` */ -class ConstructedLocalFunction extends LocalFunction, ConstructedGeneric -{ +class ConstructedLocalFunction extends LocalFunction, ConstructedGeneric { override UnboundLocalFunction getSourceDeclaration() { - result=LocalFunction.super.getSourceDeclaration() + result = LocalFunction.super.getSourceDeclaration() } override UnboundLocalFunction getUnboundGeneric() { @@ -607,9 +563,7 @@ class ConstructedLocalFunction extends LocalFunction, ConstructedGeneric * not a generic method or an unbound generic method (`UnboundGenericMethod`). */ class NonConstructedMethod extends Method { - NonConstructedMethod() { - not this instanceof ConstructedMethod - } + NonConstructedMethod() { not this instanceof ConstructedMethod } /** * Gets a method that either equals this non-constructed method, or diff --git a/csharp/ql/src/semmle/code/csharp/Implements.qll b/csharp/ql/src/semmle/code/csharp/Implements.qll index d46b67af5cd..47739a290d4 100644 --- a/csharp/ql/src/semmle/code/csharp/Implements.qll +++ b/csharp/ql/src/semmle/code/csharp/Implements.qll @@ -6,6 +6,7 @@ * Do not use the predicates in this library directly; use the methods * of the class `Virtualizable` instead. */ + import csharp private import Conversion private import dispatch.Dispatch @@ -76,7 +77,8 @@ private Virtualizable getAnImplementedInterfaceMemberForSubType(Virtualizable m, ) } -pragma [noinline] // predicate folding for proper join order +// predicate folding for proper join order +pragma[noinline] private predicate hasMemberCompatibleWithInterfaceMember(ValueOrRefType t, Virtualizable m) { m = getACompatibleInterfaceMember(t.getAMember()) } @@ -121,15 +123,16 @@ private DeclarationWithAccessors getACompatibleInterfaceAccessor(DeclarationWith } private DeclarationWithAccessors getACompatibleInterfaceAccessorCandidate(DeclarationWithAccessors d) { - getACompatibleInterfaceAccessorAux(result, d.getDeclaringType(), d.getName()) - and - not d instanceof Indexer - and + getACompatibleInterfaceAccessorAux(result, d.getDeclaringType(), d.getName()) and + not d instanceof Indexer and d.isPublic() } -pragma [noinline] // predicate folding for proper join-order -private predicate getACompatibleInterfaceAccessorAux(DeclarationWithAccessors d, ValueOrRefType t, string name) { +// predicate folding for proper join-order +pragma[noinline] +private predicate getACompatibleInterfaceAccessorAux( + DeclarationWithAccessors d, ValueOrRefType t, string name +) { t = getAPossibleImplementor(d.getDeclaringType()) and name = d.getName() } @@ -155,8 +158,7 @@ private predicate getACompatibleInterfaceAccessorAux(DeclarationWithAccessors d, */ pragma[nomagic] ValueOrRefType getAPossibleImplementor(Interface i) { - result.getASubType*().getABaseInterface+() = i - and + result.getASubType*().getABaseInterface+() = i and not result instanceof Interface } @@ -166,36 +168,33 @@ ValueOrRefType getAPossibleImplementor(Interface i) { * the interface indexer is accessed. */ private Indexer getACompatibleInterfaceIndexer(Indexer i) { - result = getACompatibleInterfaceIndexerCandidate(i) - and - convIdentity(i.getType(), result.getType()) - and - forex(int j | - j in [0 .. i.getNumberOfParameters() - 1] | + result = getACompatibleInterfaceIndexerCandidate(i) and + convIdentity(i.getType(), result.getType()) and + forex(int j | j in [0 .. i.getNumberOfParameters() - 1] | convIdentity(i.getParameter(j).getType(), result.getParameter(j).getType()) ) } private Indexer getACompatibleInterfaceIndexerCandidate(Indexer i) { - getACompatibleInterfaceIndexerAux(result, i.getDeclaringType()) - and + getACompatibleInterfaceIndexerAux(result, i.getDeclaringType()) and i.isPublic() } -pragma [noinline] // predicate folding for proper join-order +// predicate folding for proper join-order +pragma[noinline] private predicate getACompatibleInterfaceIndexerAux(Indexer i, ValueOrRefType t) { t = getAPossibleImplementor(i.getDeclaringType()) } private Method getACompatibleInterfaceMethod(Method m) { - result = getAnInterfaceMethodCandidate(m) - and - forex(int i | - i in [0 .. m.getNumberOfParameters()] | + result = getAnInterfaceMethodCandidate(m) and + forex(int i | i in [0 .. m.getNumberOfParameters()] | exists(Type t1, Type t2 | t1 = getArgumentOrReturnType(m, i) and - t2 = getArgumentOrReturnType(result, i) | - convIdentity(t1, t2) or + t2 = getArgumentOrReturnType(result, i) + | + convIdentity(t1, t2) + or // In the case where both `m` and `result` are unbound generic methods, // we need to do check for structural equality modulo the method type // parameters @@ -211,13 +210,16 @@ private Method getACompatibleInterfaceMethod(Method m) { * in a type that is a possible implementor type for the interface type. */ private Method getAnInterfaceMethodCandidate(Method m) { - getAPotentialInterfaceMethodAux(result, m.getDeclaringType(), m.getName(), m.getNumberOfParameters()) - and + getAPotentialInterfaceMethodAux(result, m.getDeclaringType(), m.getName(), + m.getNumberOfParameters()) and m.isPublic() } -pragma [nomagic] // predicate folding for proper join-order -private predicate getAPotentialInterfaceMethodAux(Method m, ValueOrRefType t, string name, int params) { +// predicate folding for proper join-order +pragma[nomagic] +private predicate getAPotentialInterfaceMethodAux( + Method m, ValueOrRefType t, string name, int params +) { t = getAPossibleImplementor(m.getDeclaringType()) and name = m.getName() and params = m.getNumberOfParameters() @@ -239,37 +241,37 @@ private Type getArgumentOrReturnType(Method m, int i) { * Here, compatibility means that the two types are structurally equal * modulo identity conversions and method type parameters. */ -private predicate structurallyCompatible(UnboundGenericMethod m1, UnboundGenericMethod m2, Type t1, Type t2) { +private predicate structurallyCompatible( + UnboundGenericMethod m1, UnboundGenericMethod m2, Type t1, Type t2 +) { candidateTypes(m1, m2, t1, t2) and ( // Base case: identity convertible convIdentity(t1, t2) or // Base case: method type parameter (at same index) - exists(int i | - structurallyCompatibleTypeParameter(m1, m2, i, t1, m2.getTypeParameter(i)) - ) + exists(int i | structurallyCompatibleTypeParameter(m1, m2, i, t1, m2.getTypeParameter(i))) or // Recursive case ( - ( - t1 instanceof PointerType and t2 instanceof PointerType - or - t1 instanceof NullableType and t2 instanceof NullableType - or - t1.(ArrayType).hasSameShapeAs((ArrayType)t2) - or - t1.(ConstructedType).getUnboundGeneric() = t2.(ConstructedType).getUnboundGeneric() - ) - and - structurallyCompatibleChildren(m1, m2, t1, t2, t1.getNumberOfChildren() - 1) - ) + t1 instanceof PointerType and t2 instanceof PointerType + or + t1 instanceof NullableType and t2 instanceof NullableType + or + t1.(ArrayType).hasSameShapeAs(t2.(ArrayType)) + or + t1.(ConstructedType).getUnboundGeneric() = t2.(ConstructedType).getUnboundGeneric() + ) and + structurallyCompatibleChildren(m1, m2, t1, t2, t1.getNumberOfChildren() - 1) ) } // Predicate folding to force joining on `candidateTypes` first -pragma [nomagic] // to prevent `private#structurallyCompatibleTypeParameter#fbbfb` -private predicate structurallyCompatibleTypeParameter(UnboundGenericMethod m1, UnboundGenericMethod m2, int i, Type t1, Type t2) { +// to prevent `private#structurallyCompatibleTypeParameter#fbbfb` +pragma[nomagic] +private predicate structurallyCompatibleTypeParameter( + UnboundGenericMethod m1, UnboundGenericMethod m2, int i, Type t1, Type t2 +) { candidateTypes(m1, m2, t1, t2) and t1 = m1.getTypeParameter(i) } @@ -277,7 +279,9 @@ private predicate structurallyCompatibleTypeParameter(UnboundGenericMethod m1, U /** * Holds if the `i+1` first children of types `x` and `y` are compatible. */ -private predicate structurallyCompatibleChildren(UnboundGenericMethod m1, UnboundGenericMethod m2, Type t1, Type t2, int i) { +private predicate structurallyCompatibleChildren( + UnboundGenericMethod m1, UnboundGenericMethod m2, Type t1, Type t2, int i +) { exists(Type t3, Type t4 | i = 0 and candidateChildren(t1, t2, i, t3, t4) and @@ -293,8 +297,7 @@ private predicate structurallyCompatibleChildren(UnboundGenericMethod m1, Unboun // manual magic predicate used to enumerate types relevant for structural comparison private predicate candidateTypes(UnboundGenericMethod m1, UnboundGenericMethod m2, Type t1, Type t2) { - m2 = getAnInterfaceMethodCandidate(m1) - and + m2 = getAnInterfaceMethodCandidate(m1) and ( exists(int i | t1 = getArgumentOrReturnType(m1, i) and @@ -309,7 +312,8 @@ private predicate candidateTypes(UnboundGenericMethod m1, UnboundGenericMethod m ) } -pragma [noinline] // predicate folding for proper join-order +// predicate folding for proper join-order +pragma[noinline] private predicate candidateChildren(Type t1, Type t2, int i, Type t3, Type t4) { candidateTypes(_, _, t1, t2) and t3 = t1.getChild(i) and diff --git a/csharp/ql/src/semmle/code/csharp/Location.qll b/csharp/ql/src/semmle/code/csharp/Location.qll index c1983e19ba1..b90d71fafb1 100644 --- a/csharp/ql/src/semmle/code/csharp/Location.qll +++ b/csharp/ql/src/semmle/code/csharp/Location.qll @@ -18,9 +18,7 @@ private import Attribute /** * A location of a program element. */ -class Location extends @location -{ - +class Location extends @location { /** Gets the file of the location. */ File getFile() { none() } @@ -31,7 +29,11 @@ class Location extends @location * For more information, see * [LGTM locations](https://lgtm.com/help/ql/locations). */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { none() } + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + none() + } /** Gets a textual representation of this location. */ string toString() { none() } @@ -54,41 +56,40 @@ class Location extends @location * within the file. */ class SourceLocation extends Location, @location_default { + override File getFile() { locations_default(this, result, _, _, _, _) } - override File getFile() { - locations_default(this,result,_,_,_,_) - } - - override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { - exists(File f | - locations_default(this, f, startline, startcolumn, endline, endcolumn) | + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + exists(File f | locations_default(this, f, startline, startcolumn, endline, endcolumn) | filepath = f.getAbsolutePath() ) } override string toString() { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | - this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) | + this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + | result = filepath + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn ) } } bindingset[version] -private int versionField(string version, int field) -{ +private int versionField(string version, int field) { exists(string format | format = "(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)" or format = "(\\d+)\\.(\\d+)\\.(\\d+)" or - format = "(\\d+)\\.(\\d+)" | - result = version.regexpCapture(format, field).toInt()) - and result >= 0 - and result <= 255 + format = "(\\d+)\\.(\\d+)" + | + result = version.regexpCapture(format, field).toInt() + ) and + result >= 0 and + result <= 255 } /** An assembly version, for example `4.0.0.0` or `4.5`. */ -class Version extends string -{ +class Version extends string { bindingset[this] Version() { exists(versionField(this, 1)) } @@ -97,13 +98,9 @@ class Version extends string * If the field is unspecified in the version string, then the result is `0`. */ bindingset[this] - int getField(int field) - { - field in [1..4] - and - if exists(versionField(this, field)) - then result = versionField(this, field) - else result = 0 + int getField(int field) { + field in [1 .. 4] and + if exists(versionField(this, field)) then result = versionField(this, field) else result = 0 } /** Gets the major version, for example `1` in `1.2.3.4`. */ @@ -133,10 +130,9 @@ class Version extends string * For example, `4.0.0.0` is earlier than `4.5`. */ bindingset[this, other] - predicate isEarlierThan(Version other) - { + predicate isEarlierThan(Version other) { exists(int i | this.getField(i) < other.getField(i) | - forall(int j | j in [1..i-1] | this.getField(j) = other.getField(j)) + forall(int j | j in [1 .. i - 1] | this.getField(j) = other.getField(j)) ) } @@ -150,9 +146,7 @@ class Version extends string int compareTo(Version other) { if this.isEarlierThan(other) then result = -1 - else if other.isEarlierThan(this) - then result = 1 - else result = 0 + else if other.isEarlierThan(this) then result = 1 else result = 0 } } @@ -160,21 +154,22 @@ class Version extends string * A .NET assembly location. */ class Assembly extends Location, Attributable, @assembly { - /** Gets the full name of this assembly, including its version and public token. */ - string getFullName() { assemblies(this,_,result,_,_) } + string getFullName() { assemblies(this, _, result, _, _) } /** Gets the name of this assembly. */ - string getName() { assemblies(this,_,_,result,_) } + string getName() { assemblies(this, _, _, result, _) } /** Gets the version of this assembly. */ - Version getVersion() { assemblies(this,_,_,_,result) } + Version getVersion() { assemblies(this, _, _, _, result) } - override File getFile() { assemblies(this,result,_,_,_) } + override File getFile() { assemblies(this, result, _, _, _) } override string toString() { result = this.getFullName() } - override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { exists(File f | assemblies(this, f, _, _, _) and filepath = f.getAbsolutePath() and diff --git a/csharp/ql/src/semmle/code/csharp/Member.qll b/csharp/ql/src/semmle/code/csharp/Member.qll index 10200635f19..7721058da49 100644 --- a/csharp/ql/src/semmle/code/csharp/Member.qll +++ b/csharp/ql/src/semmle/code/csharp/Member.qll @@ -16,7 +16,7 @@ class Declaration extends DotNet::Declaration, Element, @declaration { override ValueOrRefType getDeclaringType() { none() } /** Holds if this declaration is unconstructed and in source code. */ - predicate isSourceDeclaration() { fromSource() and this=getSourceDeclaration() } + predicate isSourceDeclaration() { fromSource() and this = getSourceDeclaration() } override string toString() { result = this.getName() } @@ -40,9 +40,7 @@ class Declaration extends DotNet::Declaration, Element, @declaration { * Holds if this declaration has been generated by the compiler, for example * implicit constructors or accessors. */ - predicate isCompilerGenerated() { - compiler_generated(this) - } + predicate isCompilerGenerated() { compiler_generated(this) } } /** A declaration that can have a modifier. */ @@ -140,29 +138,23 @@ class Virtualizable extends Member, @virtualizable { * to members that can be declared on an interface, i.e. methods, properties, * indexers and events. */ - Interface getExplicitlyImplementedInterface() { - explicitly_implements(this, getTypeRef(result)) - } + Interface getExplicitlyImplementedInterface() { explicitly_implements(this, getTypeRef(result)) } /** * Holds if this member implements an interface member explicitly. */ - predicate implementsExplicitInterface() { - exists(getExplicitlyImplementedInterface()) - } + predicate implementsExplicitInterface() { exists(getExplicitlyImplementedInterface()) } /** Holds if this member can be overridden or implemented. */ predicate isOverridableOrImplementable() { - not isSealed() - and - not getDeclaringType().isSealed() - and - ( - isVirtual() or - isOverride() or - isAbstract() or - getDeclaringType() instanceof Interface - ) + not isSealed() and + not getDeclaringType().isSealed() and + ( + isVirtual() or + isOverride() or + isAbstract() or + getDeclaringType() instanceof Interface + ) } /** Gets the member that is immediately overridden by this member, if any. */ @@ -273,7 +265,8 @@ class Virtualizable extends Member, @virtualizable { */ Virtualizable getAnUltimateImplementee() { exists(Virtualizable implementation, ValueOrRefType implementationType | - implements(implementation, result, implementationType) | + implements(implementation, result, implementationType) + | this = implementation or getOverridee+() = implementation and @@ -333,15 +326,14 @@ class Parameterizable extends Declaration, @parameterizable { private string parameterTypeToString(int i) { exists(Parameter p, string prefix | p = getParameter(i) and - result = prefix + p.getType().toStringWithTypes() | - if p.isOut() then - prefix = "out " - else if p.isRef() then - prefix = "ref " - else if p.isParams() then - prefix = "params " + result = prefix + p.getType().toStringWithTypes() + | + if p.isOut() + then prefix = "out " else - prefix = "" + if p.isRef() + then prefix = "ref " + else if p.isParams() then prefix = "params " else prefix = "" ) } @@ -349,11 +341,8 @@ class Parameterizable extends Declaration, @parameterizable { * Gets the types of the parameters of this declaration as a * comma-separated string. */ - language [monotonicAggregates] + language[monotonicAggregates] string parameterTypesToString() { - result = concat(int i | - exists(getParameter(i)) | - parameterTypeToString(i), ", " order by i asc - ) + result = concat(int i | exists(getParameter(i)) | parameterTypeToString(i), ", " order by i) } } diff --git a/csharp/ql/src/semmle/code/csharp/Modifier.qll b/csharp/ql/src/semmle/code/csharp/Modifier.qll index c4a557cc29a..542598d204e 100644 --- a/csharp/ql/src/semmle/code/csharp/Modifier.qll +++ b/csharp/ql/src/semmle/code/csharp/Modifier.qll @@ -6,7 +6,6 @@ import Element * A modifier, for example `static`, `virtual`, `public` and so on. */ class Modifier extends Element, @modifier { - /** Gets the name of this modifier, for example `public`. */ string getName() { modifiers(this, result) } diff --git a/csharp/ql/src/semmle/code/csharp/Namespace.qll b/csharp/ql/src/semmle/code/csharp/Namespace.qll index e8d7a96e6b9..ddbad94fd3f 100644 --- a/csharp/ql/src/semmle/code/csharp/Namespace.qll +++ b/csharp/ql/src/semmle/code/csharp/Namespace.qll @@ -106,7 +106,8 @@ class Namespace extends DotNet::Namespace, TypeContainer, @namespace { DelegateType getADelegate() { result = this.getATypeDeclaration() } override predicate fromSource() { - exists(ValueOrRefType t | t.getNamespace() = this and t.fromSource()) or + exists(ValueOrRefType t | t.getNamespace() = this and t.fromSource()) + or exists(Namespace n | n.getParentNamespace() = this and n.fromSource()) } @@ -115,18 +116,13 @@ class Namespace extends DotNet::Namespace, TypeContainer, @namespace { /** Gets a declaration of this namespace, if any. */ NamespaceDeclaration getADeclaration() { result.getNamespace() = this } - override Location getALocation() { - result = this.getADeclaration().getALocation() - } + override Location getALocation() { result = this.getADeclaration().getALocation() } } /** * The global namespace. This is the root of all namespaces. */ -class GlobalNamespace extends Namespace { - - GlobalNamespace() { this.hasName("") } -} +class GlobalNamespace extends Namespace { GlobalNamespace() { this.hasName("") } } /** * An explicit namespace declaration in a source file. For example: @@ -138,7 +134,6 @@ class GlobalNamespace extends Namespace { * ``` */ class NamespaceDeclaration extends Element, @namespace_declaration { - /** * Gets the declared namespace, for example `N1.N2` in * @@ -148,7 +143,7 @@ class NamespaceDeclaration extends Element, @namespace_declaration { * } * ``` */ - Namespace getNamespace() { namespace_declarations(this,result) } + Namespace getNamespace() { namespace_declarations(this, result) } /** * Gets the parent namespace declaration, if any. In the following example, @@ -168,7 +163,9 @@ class NamespaceDeclaration extends Element, @namespace_declaration { * } * ``` */ - NamespaceDeclaration getParentNamespaceDeclaration() { parent_namespace_declaration(this,result) } + NamespaceDeclaration getParentNamespaceDeclaration() { + parent_namespace_declaration(this, result) + } /** * Gets a child namespace declaration, if any. In the following example, @@ -182,8 +179,10 @@ class NamespaceDeclaration extends Element, @namespace_declaration { * } * } * ``` - */ - NamespaceDeclaration getAChildNamespaceDeclaration() { parent_namespace_declaration(result,this) } + */ + NamespaceDeclaration getAChildNamespaceDeclaration() { + parent_namespace_declaration(result, this) + } /** * Gets a type directly declared within this namespace declaration. diff --git a/csharp/ql/src/semmle/code/csharp/Property.qll b/csharp/ql/src/semmle/code/csharp/Property.qll index fbb0806067e..6038c7c684d 100644 --- a/csharp/ql/src/semmle/code/csharp/Property.qll +++ b/csharp/ql/src/semmle/code/csharp/Property.qll @@ -12,15 +12,12 @@ private import dotnet * A declaration that may have accessors. Either an event (`Event`), a property * (`Property`), or an indexer (`Indexer`). */ -class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attributable, @declaration_with_accessors { +class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attributable, + @declaration_with_accessors { /** Gets an accessor of this declaration. */ - Accessor getAnAccessor() { - result.getDeclaration() = this - } + Accessor getAnAccessor() { result.getDeclaration() = this } - override DeclarationWithAccessors getOverridee() { - result = Virtualizable.super.getOverridee() - } + override DeclarationWithAccessors getOverridee() { result = Virtualizable.super.getOverridee() } override DeclarationWithAccessors getAnOverrider() { result = Virtualizable.super.getAnOverrider() @@ -53,7 +50,8 @@ class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attribut * A declaration that may have a `get` accessor and a `set` accessor. Either a * property (`Property`) or an indexer (`Indexer`). */ -class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelExprParent, @assignable_with_accessors { +class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelExprParent, + @assignable_with_accessors { /** Gets the `get` accessor of this declaration, if any. */ Getter getGetter() { result = getAnAccessor() } @@ -103,9 +101,7 @@ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelE } /** Gets the expression body of this declaration, if any. */ - Expr getExpressionBody() { - result = this.getChildExpr(0) - } + Expr getExpressionBody() { result = this.getChildExpr(0) } } /** @@ -118,17 +114,11 @@ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelE * ``` */ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @property { - override string getName() { - properties(this, result, _, _, _) - } + override string getName() { properties(this, result, _, _, _) } - override ValueOrRefType getDeclaringType() { - properties(this, _, result, _, _) - } + override ValueOrRefType getDeclaringType() { properties(this, _, result, _, _) } - override Type getType() { - properties(this, _, _, getTypeRef(result), _) - } + override Type getType() { properties(this, _, _, getTypeRef(result), _) } /** * Holds if this property is automatically implemented. For example, `P1` @@ -157,13 +147,9 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper not this.getAnAccessor().hasBody() } - override Property getSourceDeclaration() { - properties(this, _, _, _, result) - } + override Property getSourceDeclaration() { properties(this, _, _, _, result) } - override Property getOverridee() { - result = DeclarationWithGetSetAccessors.super.getOverridee() - } + override Property getOverridee() { result = DeclarationWithGetSetAccessors.super.getOverridee() } override Property getAnOverrider() { result = DeclarationWithGetSetAccessors.super.getAnOverrider() @@ -185,28 +171,23 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper result = DeclarationWithGetSetAccessors.super.getAnUltimateImplementor() } - override PropertyAccess getAnAccess() { - result.getTarget() = this - } + override PropertyAccess getAnAccess() { result.getTarget() = this } - override Location getALocation() { - property_location(this, result) - } + override Location getALocation() { property_location(this, result) } override Expr getAnAssignedValue() { result = DeclarationWithGetSetAccessors.super.getAnAssignedValue() or - /* - * For library types, we don't know about assignments in constructors. We instead assume that - * arguments passed to parameters of constructors with suitable names. - */ + // For library types, we don't know about assignments in constructors. We instead assume that + // arguments passed to parameters of constructors with suitable names. getDeclaringType().fromLibrary() and exists(Parameter param, Constructor c, string propertyName | propertyName = getName() and c = getDeclaringType().getAConstructor() and param = c.getAParameter() and // Find a constructor parameter with the same name, but with a lower case initial letter. - param.hasName(propertyName.charAt(0).toLowerCase() + propertyName.suffix(1)) | + param.hasName(propertyName.charAt(0).toLowerCase() + propertyName.suffix(1)) + | result = param.getAnAssignedArgument() ) } @@ -238,6 +219,7 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper } override Getter getGetter() { result = DeclarationWithGetSetAccessors.super.getGetter() } + override Setter getSetter() { result = DeclarationWithGetSetAccessors.super.getSetter() } } @@ -253,26 +235,16 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper * ``` */ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer { - override string getName() { - indexers(this, result, _, _, _) - } + override string getName() { indexers(this, result, _, _, _) } /** Gets the dimension of this indexer, that is, its number of parameters. */ - int getDimension() { - result = getNumberOfParameters() - } + int getDimension() { result = getNumberOfParameters() } - override ValueOrRefType getDeclaringType() { - indexers(this, _, result, _, _) - } + override ValueOrRefType getDeclaringType() { indexers(this, _, result, _, _) } - override Type getType() { - indexers(this, _, _, getTypeRef(result), _) - } + override Type getType() { indexers(this, _, _, getTypeRef(result), _) } - override IndexerAccess getAnAccess() { - result.getTarget() = this - } + override IndexerAccess getAnAccess() { result.getTarget() = this } /** * Gets the expression body of this indexer, if any. For example, the @@ -288,13 +260,9 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer result = DeclarationWithGetSetAccessors.super.getExpressionBody() } - override Indexer getSourceDeclaration() { - indexers(this, _, _, _, result) - } + override Indexer getSourceDeclaration() { indexers(this, _, _, _, result) } - override Indexer getOverridee() { - result = DeclarationWithGetSetAccessors.super.getOverridee() - } + override Indexer getOverridee() { result = DeclarationWithGetSetAccessors.super.getOverridee() } override Indexer getAnOverrider() { result = DeclarationWithGetSetAccessors.super.getAnOverrider() @@ -316,13 +284,9 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer result = DeclarationWithGetSetAccessors.super.getAnUltimateImplementor() } - override Location getALocation() { - indexer_location(this, result) - } + override Location getALocation() { indexer_location(this, result) } - override string toStringWithTypes() { - result = getName() + "[" + parameterTypesToString() + "]" - } + override string toStringWithTypes() { result = getName() + "[" + parameterTypesToString() + "]" } } /** @@ -330,14 +294,10 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer * accessor (`EventAccessor`). */ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { - override ValueOrRefType getDeclaringType() { - result = this.getDeclaration().getDeclaringType() - } + override ValueOrRefType getDeclaringType() { result = this.getDeclaration().getDeclaringType() } /** Gets the assembly name of this accessor. */ - string getAssemblyName() { - accessors(this, _, result, _, _) - } + string getAssemblyName() { accessors(this, _, result, _, _) } /** * Gets the declaration that this accessor belongs to. For example, both @@ -352,9 +312,7 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { * } * ``` */ - DeclarationWithAccessors getDeclaration() { - accessors(this, _ , _, result, _) - } + DeclarationWithAccessors getDeclaration() { accessors(this, _, _, result, _) } /** * Gets an explicit access modifier of this accessor, if any. For example, @@ -370,9 +328,7 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { * } * ``` */ - AccessModifier getAnAccessModifier() { - result = Modifiable.super.getAModifier() - } + AccessModifier getAnAccessModifier() { result = Modifiable.super.getAModifier() } /** * Gets a modifier of this accessor, if any. @@ -398,17 +354,11 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { not (result instanceof AccessModifier and exists(getAnAccessModifier())) } - override Accessor getSourceDeclaration() { - accessors(this, _, _, _, result) - } + override Accessor getSourceDeclaration() { accessors(this, _, _, _, result) } - override Location getALocation() { - accessor_location(this, result) - } + override Location getALocation() { accessor_location(this, result) } - override string toString() { - result = getName() - } + override string toString() { result = getName() } override Location getLocation() { result = Callable.super.getLocation() } } @@ -427,13 +377,9 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor { * ``` */ class Getter extends Accessor, @getter { - override string getName() { - result = "get" + "_" + getDeclaration().getName() - } + override string getName() { result = "get" + "_" + getDeclaration().getName() } - override Type getReturnType() { - result = getDeclaration().getType() - } + override Type getReturnType() { result = getDeclaration().getType() } /** * Gets the field used in the trival implementation of this getter, if any. @@ -476,9 +422,7 @@ class Getter extends Accessor, @getter { * ``` */ class Setter extends Accessor, @setter { - override string getName() { - result = "set" + "_" + getDeclaration().getName() - } + override string getName() { result = "set" + "_" + getDeclaration().getName() } override Type getReturnType() { exists(this) and // needed to avoid compiler warning @@ -516,8 +460,7 @@ class Setter extends Accessor, @setter { /** * Gets an access to the special `value` parameter available in setters. */ -private -ParameterAccess accessToValue() { +private ParameterAccess accessToValue() { result.getTarget().hasName("value") and result.getEnclosingCallable() instanceof Setter } @@ -547,8 +490,7 @@ ParameterAccess accessToValue() { * } * ``` */ -class TrivialProperty extends Property -{ +class TrivialProperty extends Property { TrivialProperty() { isAutoImplemented() or @@ -560,9 +502,7 @@ class TrivialProperty extends Property * A `Property` which holds a type with an indexer. */ class IndexerProperty extends Property { - IndexerProperty() { - exists(getType().(RefType).getABaseType*().getAnIndexer()) - } + IndexerProperty() { exists(getType().(RefType).getABaseType*().getAnIndexer()) } /** * Gets a call to the indexer of the type returned by this property, for a value returned by this @@ -573,8 +513,7 @@ class IndexerProperty extends Property { IndexerCall getAnIndexerCall() { result = getType().(RefType).getAnIndexer().getAnAccessor().getACall() and // The qualifier of this indexer call should be a value returned from an access of this property - exists(Expr qualifier | - qualifier = result.(IndexerAccess).getQualifier() | + exists(Expr qualifier | qualifier = result.(IndexerAccess).getQualifier() | DataFlow::localFlow(DataFlow::exprNode(this.getAnAccess()), DataFlow::exprNode(qualifier)) ) } diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index 199030e341a..51f1ccaefb0 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -25,11 +25,8 @@ private import semmle.code.csharp.frameworks.System * (`FixedStmt`). */ class Stmt extends ControlFlowElement, @stmt { - /** Gets the enclosing callable of this statement. */ - override Callable getEnclosingCallable() { - enclosingCallable(this, result) - } + override Callable getEnclosingCallable() { enclosingCallable(this, result) } override string toString() { result = "Statement" } @@ -54,7 +51,6 @@ class Stmt extends ControlFlowElement, @stmt { * ``` */ class BlockStmt extends Stmt, @block_stmt { - /** Gets a statement in this block, if any. */ Stmt getAStmt() { result.getParent() = this } @@ -74,10 +70,9 @@ class BlockStmt extends Stmt, @block_stmt { predicate isEmpty() { not exists(this.getAStmt()) } override Stmt stripSingletonBlocks() { - if getNumberOfStmts() = 1 then - result = getAChildStmt().stripSingletonBlocks() - else - result = this + if getNumberOfStmts() = 1 + then result = getAChildStmt().stripSingletonBlocks() + else result = this } override string toString() { result = "{...}" } @@ -97,7 +92,6 @@ class BlockStmt extends Stmt, @block_stmt { * ``` */ class ExprStmt extends Stmt, @expr_stmt { - /** Gets the expression in this expression statement. */ Expr getExpr() { result.getParent() = this } @@ -110,7 +104,6 @@ class ExprStmt extends Stmt, @expr_stmt { * Either an `if` statement (`IfStmt`) or a `switch` statement (`SwitchStmt`). */ class SelectionStmt extends Stmt, @cond_stmt { - /** Gets the condition of this selection statement. */ Expr getCondition() { none() } } @@ -129,7 +122,6 @@ class SelectionStmt extends Stmt, @cond_stmt { * The `else` part is optional. */ class IfStmt extends SelectionStmt, @if_stmt { - override Expr getCondition() { result = this.getChild(0) } /** Gets the `then` (true) branch of this `if` statement. */ @@ -151,7 +143,6 @@ class IfStmt extends SelectionStmt, @if_stmt { * ``` */ class SwitchStmt extends SelectionStmt, @switch_stmt { - override Expr getCondition() { result = this.getChild(0) } /** @@ -217,16 +208,14 @@ class SwitchStmt extends SelectionStmt, @switch_stmt { Stmt getAStmt() { result = this.getStmt(_) } } -private cached module SwithStmtInternal { +cached +private module SwithStmtInternal { cached CaseStmt getCase(SwitchStmt ss, int i) { exists(int index, int rankIndex | result = ss.getChildStmt(index) and rankIndex = i + 1 and - index = rank[rankIndex](int j, CaseStmt cs | - cs = ss.getChildStmt(j) | - j - ) + index = rank[rankIndex](int j, CaseStmt cs | cs = ss.getChildStmt(j) | j) ) } @@ -236,12 +225,13 @@ private cached module SwithStmtInternal { result = ss.getChildStmt(index) and rankIndex = i + 1 and index = rank[rankIndex](int j, Stmt s | - // `getChild` includes both labeled statements and the targeted - // statements of labeled statement as separate children, but we - // only want the labeled statement - s = getLabeledStmt(ss, j) | - j - ) + // `getChild` includes both labeled statements and the targeted + // statements of labeled statement as separate children, but we + // only want the labeled statement + s = getLabeledStmt(ss, j) + | + j + ) ) } @@ -271,9 +261,7 @@ class CaseStmt extends Stmt, @case { * } * ``` */ - Expr getCondition() { - result = this.getChild(2) - } + Expr getCondition() { result = this.getChild(2) } } /** @@ -318,9 +306,7 @@ class ConstCase extends LabeledStmt, CaseStmt { * ``` */ class TypeCase extends LabeledStmt, CaseStmt { - TypeCase() { - this.getChild(1) instanceof TypeAccess - } + TypeCase() { this.getChild(1) instanceof TypeAccess } /** * Gets the local variable declaration of this type case, if any. For example, @@ -337,9 +323,7 @@ class TypeCase extends LabeledStmt, CaseStmt { * } * ``` */ - LocalVariableDeclExpr getVariableDeclExpr() { - result = getChild(0) - } + LocalVariableDeclExpr getVariableDeclExpr() { result = getChild(0) } /** * Gets the type access of this case, for example access to `string` or @@ -354,9 +338,7 @@ class TypeCase extends LabeledStmt, CaseStmt { * } * ``` */ - TypeAccess getTypeAccess() { - result = getChild(1) - } + TypeAccess getTypeAccess() { result = getChild(1) } /** * Gets the type being checked by this case. For example, the type being checked @@ -371,17 +353,14 @@ class TypeCase extends LabeledStmt, CaseStmt { * } * ``` */ - Type getCheckedType() { - result = getTypeAccess().getType() - } + Type getCheckedType() { result = getTypeAccess().getType() } override string toString() { exists(string var | - if exists(this.getVariableDeclExpr()) then - var = " " + this.getVariableDeclExpr().getName() - else - var = "" - | + if exists(this.getVariableDeclExpr()) + then var = " " + this.getVariableDeclExpr().getName() + else var = "" + | result = "case " + this.getTypeAccess().getType().getName() + var + ":" ) } @@ -399,7 +378,6 @@ class TypeCase extends LabeledStmt, CaseStmt { * ``` */ class DefaultCase extends CaseStmt { - DefaultCase() { not exists(Expr e | e.getParent() = this) } override string toString() { result = "default:" } @@ -413,7 +391,6 @@ class DefaultCase extends CaseStmt { * (`ForeachStmt`). */ class LoopStmt extends Stmt, @loop_stmt { - /** Gets the body of this loop statement. */ Stmt getBody() { result.getParent() = this } @@ -431,7 +408,6 @@ class LoopStmt extends Stmt, @loop_stmt { * ``` */ class WhileStmt extends LoopStmt, @while_stmt { - override Expr getCondition() { result.getParent() = this } override string toString() { result = "while (...) ..." } @@ -448,7 +424,6 @@ class WhileStmt extends LoopStmt, @while_stmt { * ``` */ class DoStmt extends LoopStmt, @do_stmt { - override Expr getCondition() { result.getParent() = this } override string toString() { result = "do ... while (...);" } @@ -464,7 +439,6 @@ class DoStmt extends LoopStmt, @do_stmt { * ``` */ class ForStmt extends LoopStmt, @for_stmt { - /** * Gets an initializer expression of this `for` loop, if any. * @@ -490,7 +464,9 @@ class ForStmt extends LoopStmt, @for_stmt { * } * ``` */ - Expr getInitializer(int n) { exists(int i | result = this.getChild(i) and n = -1-i and i <= -1) } + Expr getInitializer(int n) { + exists(int i | result = this.getChild(i) and n = -1 - i and i <= -1) + } override Expr getCondition() { result = this.getChild(0) } @@ -518,7 +494,7 @@ class ForStmt extends LoopStmt, @for_stmt { * } * ``` */ - Expr getUpdate(int n) { exists(int i | result = this.getChild(i) and n = i-1 and i >= 1) } + Expr getUpdate(int n) { exists(int i | result = this.getChild(i) and n = i - 1 and i >= 1) } override string toString() { result = "for (...;...;...) ..." } } @@ -532,8 +508,7 @@ class ForStmt extends LoopStmt, @for_stmt { * } * ``` */ -class ForeachStmt extends LoopStmt, @foreach_stmt { - +class ForeachStmt extends LoopStmt, @foreach_stmt { /** * Gets the local variable of this `foreach` loop, if any. * @@ -572,8 +547,9 @@ class ForeachStmt extends LoopStmt, @foreach_stmt { * ``` */ LocalVariableDeclExpr getVariableDeclExpr(int i) { - result = getVariableDeclTuple().getArgument(i) or - i=0 and result = this.getChild(0) + result = getVariableDeclTuple().getArgument(i) + or + i = 0 and result = this.getChild(0) } /** @@ -665,9 +641,7 @@ class JumpStmt extends Stmt, @jump_stmt { } * } * ``` */ -class BreakStmt extends JumpStmt, @break_stmt { - override string toString() { result = "break;" } -} +class BreakStmt extends JumpStmt, @break_stmt { override string toString() { result = "break;" } } /** * A `continue` statement, for example line 4 in @@ -690,7 +664,6 @@ class ContinueStmt extends JumpStmt, @continue_stmt { * * Either a `goto` label (`GotoLabelStmt`), a `goto case` (`GotoCaseStmt`), or * a `goto default` (`GotoDefaultStmt`). - * */ class GotoStmt extends JumpStmt, @goto_any_stmt { } @@ -707,7 +680,6 @@ class GotoStmt extends JumpStmt, @goto_any_stmt { } * ``` */ class GotoLabelStmt extends GotoStmt, @goto_stmt { - /** Gets the label that this `goto` statement jumps to. */ string getLabel() { exprorstmt_name(this, result) } @@ -715,8 +687,7 @@ class GotoLabelStmt extends GotoStmt, @goto_stmt { /** Gets the target statement that this `goto` statement jumps to. */ LabeledStmt getTarget() { - result.getEnclosingCallable() = getEnclosingCallable() - and + result.getEnclosingCallable() = getEnclosingCallable() and result.getLabel() = getLabel() } } @@ -738,7 +709,6 @@ class GotoLabelStmt extends GotoStmt, @goto_stmt { * ``` */ class GotoCaseStmt extends GotoStmt, @goto_case_stmt { - /** Gets the constant expression that this `goto case` statement jumps to. */ Expr getExpr() { result = this.getChild(0) } @@ -803,9 +773,7 @@ class ThrowStmt extends JumpStmt, ThrowElement, @throw_stmt { * and may be thrown as an exception. */ class ExceptionClass extends Class { - ExceptionClass() { - getBaseClass*() instanceof SystemExceptionClass - } + ExceptionClass() { getBaseClass*() instanceof SystemExceptionClass } } /** @@ -818,7 +786,6 @@ class ExceptionClass extends Class { * ``` */ class ReturnStmt extends JumpStmt, @return_stmt { - /** Gets the expression being returned, if any. */ Expr getExpr() { result.getParent() = this } @@ -832,7 +799,6 @@ class ReturnStmt extends JumpStmt, @return_stmt { * `yield break` statement (`YieldBreakStmt`). */ class YieldStmt extends JumpStmt, @yield_stmt { - /** Gets the expression being yielded, if any. */ Expr getExpr() { result.getParent() = this } } @@ -893,7 +859,6 @@ class YieldReturnStmt extends YieldStmt { * ``` */ class TryStmt extends Stmt, @try_stmt { - /** Gets the block of this `try` statement. */ BlockStmt getBlock() { result = this.getChild(0) } @@ -901,7 +866,7 @@ class TryStmt extends Stmt, @try_stmt { CatchClause getACatchClause() { result = this.getAChild() } /** Gets the `n`th catch clause of this `try` statement. */ - CatchClause getCatchClause(int n) { exists(int i | result = this.getChild(i) and n = i-1) } + CatchClause getCatchClause(int n) { exists(int i | result = this.getChild(i) and n = i - 1) } /** Gets the `finally` block of this `try` statement, if any. */ BlockStmt getFinally() { result = this.getChild(-1) } @@ -912,18 +877,14 @@ class TryStmt extends Stmt, @try_stmt { override string toString() { result = "try {...} ..." } /** Gets the `catch` clause that handles an exception of type `ex`, if any. */ - CatchClause getAnExceptionHandler(ExceptionClass ex) { - result = clauseHandlesException(ex, 0) - } + CatchClause getAnExceptionHandler(ExceptionClass ex) { result = clauseHandlesException(ex, 0) } /** * Holds if catch clause `cc` definitely handles exceptions of type `ex`. */ predicate definitelyHandles(ExceptionClass ex, CatchClause cc) { - cc=getACatchClause() - and - not exists(cc.getFilterClause()) - and + cc = getACatchClause() and + not exists(cc.getFilterClause()) and ( cc.getCaughtExceptionType() = ex.getBaseClass*() or @@ -932,26 +893,23 @@ class TryStmt extends Stmt, @try_stmt { } private predicate maybeHandles(ExceptionClass ex, CatchClause cc) { - cc=getACatchClause() - and + cc = getACatchClause() and cc.getCaughtExceptionType().getBaseClass*() = ex } private CatchClause clauseHandlesException(ExceptionClass ex, int n) { - exists(CatchClause clause | - clause = getCatchClause(n) | - if - definitelyHandles(ex, clause) - then - result = clause - else if - maybeHandles(ex, clause) - then - result = clause or - result = clauseHandlesException(ex, n+1) - else // Does not handle - result = clauseHandlesException(ex, n+1) - ) + exists(CatchClause clause | clause = getCatchClause(n) | + if definitelyHandles(ex, clause) + then result = clause + else + if maybeHandles(ex, clause) + then + result = clause or + result = clauseHandlesException(ex, n + 1) + else + // Does not handle + result = clauseHandlesException(ex, n + 1) + ) } /** @@ -1003,7 +961,7 @@ class CatchClause extends Stmt, @catch { * } * ``` */ - ExceptionClass getCaughtExceptionType() { catch_type(this,getTypeRef(result),_) } + ExceptionClass getCaughtExceptionType() { catch_type(this, getTypeRef(result), _) } /** * Gets the `catch` filter clause, if any. For example, the filter expression @@ -1018,7 +976,7 @@ class CatchClause extends Stmt, @catch { * } * ``` */ - Expr getFilterClause() { result=getChild(2) } + Expr getFilterClause() { result = getChild(2) } /** Holds if this `catch` clause has a filter. */ predicate hasFilterClause() { exists(getFilterClause()) } @@ -1050,8 +1008,7 @@ class CatchClause extends Stmt, @catch { * The exception variable (`ex`) is optional. */ class SpecificCatchClause extends CatchClause { - - SpecificCatchClause() { catch_type(this,_,1) } + SpecificCatchClause() { catch_type(this, _, 1) } /** Gets the local variable of this catch clause, if any. */ LocalVariable getVariable() { result = this.getVariableDeclExpr().getVariable() } @@ -1077,11 +1034,9 @@ class SpecificCatchClause extends CatchClause { * ``` */ class GeneralCatchClause extends CatchClause { - - GeneralCatchClause() { catch_type(this,_,2) } + GeneralCatchClause() { catch_type(this, _, 2) } override string toString() { result = "catch {...}" } - } /** @@ -1095,7 +1050,6 @@ class GeneralCatchClause extends CatchClause { * ``` */ class CheckedStmt extends Stmt, @checked_stmt { - /** Gets the block of this `checked` statement. */ BlockStmt getBlock() { result.getParent() = this } @@ -1113,7 +1067,6 @@ class CheckedStmt extends Stmt, @checked_stmt { * ``` */ class UncheckedStmt extends Stmt, @unchecked_stmt { - /** Gets the block of this unchecked statement. */ BlockStmt getBlock() { result.getParent() = this } @@ -1130,7 +1083,6 @@ class UncheckedStmt extends Stmt, @unchecked_stmt { * ``` */ class LockStmt extends Stmt, @lock_stmt { - /** Gets the expression being locked. */ Expr getExpr() { result.getParent() = this } @@ -1140,31 +1092,22 @@ class LockStmt extends Stmt, @lock_stmt { override string toString() { result = "lock (...) {...}" } /** Gets the variable being locked, if any. */ - Variable getLockVariable() - { - result.getAnAccess() = getExpr() - } + Variable getLockVariable() { result.getAnAccess() = getExpr() } /** Gets a statement in the scope of this `lock` statement. */ - Stmt getALockedStmt() - { + Stmt getALockedStmt() { // Do this instead of getParent+, because we don't want to escape // delegates and lambdas result.getParent() = this - or exists( Stmt mid | mid=getALockedStmt() and result.getParent()=mid ) + or + exists(Stmt mid | mid = getALockedStmt() and result.getParent() = mid) } /** Holds if this statement is of the form `lock(this) { ... }`. */ - predicate isLockThis() - { - getExpr() instanceof ThisAccess - } + predicate isLockThis() { getExpr() instanceof ThisAccess } /** Gets the type `T` if this statement is of the form `lock(typeof(T)) { ... }`. */ - Type getLockTypeObject() - { - result = ((TypeofExpr)getExpr()).getTypeAccess().getTarget() - } + Type getLockTypeObject() { result = getExpr().(TypeofExpr).getTypeAccess().getTarget() } } /** @@ -1177,7 +1120,6 @@ class LockStmt extends Stmt, @lock_stmt { * ``` */ class UsingStmt extends Stmt, @using_stmt { - /** Gets the `i`th local variable of this `using` statement. */ LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() } @@ -1201,9 +1143,7 @@ class UsingStmt extends Stmt, @using_stmt { * } * ``` */ - Expr getExpr() { - result = this.getChild(0) - } + Expr getExpr() { result = this.getChild(0) } /** * Gets an expression that is used in this `using` statement. Either an @@ -1247,7 +1187,6 @@ class UsingStmt extends Stmt, @using_stmt { * ``` */ class LocalVariableDeclStmt extends Stmt, @decl_stmt { - /** * Gets a local variable declaration, for example `x = null` and * `y = ""` in @@ -1273,7 +1212,6 @@ class LocalVariableDeclStmt extends Stmt, @decl_stmt { LocalVariableDeclExpr getVariableDeclExpr(int n) { result = this.getChild(n) } override string toString() { result = "... ...;" } - } /** @@ -1286,7 +1224,6 @@ class LocalVariableDeclStmt extends Stmt, @decl_stmt { * ``` */ class LocalConstantDeclStmt extends LocalVariableDeclStmt, @const_decl_stmt { - /** * Gets a local constant declaration, for example `x = 1` and `y = 2` in * @@ -1322,10 +1259,7 @@ class LocalConstantDeclStmt extends LocalVariableDeclStmt, @const_decl_stmt { * } * ``` */ -class EmptyStmt extends Stmt, @empty_stmt { - - override string toString() { result = ";" } -} +class EmptyStmt extends Stmt, @empty_stmt { override string toString() { result = ";" } } /** * An `unsafe` statement, for example @@ -1340,7 +1274,6 @@ class EmptyStmt extends Stmt, @empty_stmt { * ``` */ class UnsafeStmt extends Stmt, @unsafe_stmt { - /** Gets the block of this unsafe statement. */ BlockStmt getBlock() { result.getParent() = this } @@ -1360,7 +1293,6 @@ class UnsafeStmt extends Stmt, @unsafe_stmt { * ``` */ class FixedStmt extends Stmt, @fixed_stmt { - /** Gets the `i`th local variable of this `fixed` statement. */ LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() } @@ -1392,8 +1324,7 @@ class FixedStmt extends Stmt, @fixed_stmt { * exit: ... * ``` */ -class LabelStmt extends LabeledStmt, @label_stmt { -} +class LabelStmt extends LabeledStmt, @label_stmt { } /** * A labeled statement. @@ -1401,7 +1332,6 @@ class LabelStmt extends LabeledStmt, @label_stmt { * Either a `case` statement (`ConstCase`) or a label statement (`LabelStmt`). */ class LabeledStmt extends Stmt, @labeled_stmt { - /** * Gets the next statement after this labeled statement. * @@ -1413,8 +1343,10 @@ class LabeledStmt extends Stmt, @labeled_stmt { * ``` */ Stmt getStmt() { - exists(int i | this = this.getParent().getChild(i) - and result = this.getParent().getChild(i+1)) + exists(int i | + this = this.getParent().getChild(i) and + result = this.getParent().getChild(i + 1) + ) } /** Gets the label of this statement. */ @@ -1438,11 +1370,8 @@ class LabeledStmt extends Stmt, @labeled_stmt { * ``` */ class LocalFunctionStmt extends Stmt, @local_function_stmt { - /** Gets the local function defined by this statement. */ - LocalFunction getLocalFunction() { - local_function_stmts(this, result) - } + LocalFunction getLocalFunction() { local_function_stmts(this, result) } override string toString() { result = getLocalFunction().getName() + "(...)" } } diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index f5f4636275c..c0f4278590c 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -18,19 +18,14 @@ private import dotnet * type (`UnknownType`), or a type parameter (`TypeParameter`). */ class Type extends DotNet::Type, Member, TypeContainer, @type { - - override string getName() { types(this,_,result) } + override string getName() { types(this, _, result) } override Type getSourceDeclaration() { result = this } /** Holds if this type is implicitly convertible to `that` type. */ - predicate isImplicitlyConvertibleTo(Type that) { - implicitConversion(this, that) - } + predicate isImplicitlyConvertibleTo(Type that) { implicitConversion(this, that) } - override Location getALocation() { - type_location(this, result) - } + override Location getALocation() { type_location(this, result) } override Type getChild(int n) { none() } @@ -50,7 +45,6 @@ class Type extends DotNet::Type, Member, TypeContainer, @type { * Either a value type (`ValueType`) or a reference type (`RefType`). */ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_or_ref_type { - /** * Holds if this type has the qualified name `qualifier`.`name`. * @@ -59,37 +53,35 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ */ override predicate hasQualifiedName(string qualifier, string name) { name = this.getName() and - if exists(this.getDeclaringType()) then - qualifier = this.getDeclaringType().getQualifiedName() - else - qualifier = this.getNamespace().getQualifiedName() + if exists(this.getDeclaringType()) + then qualifier = this.getDeclaringType().getQualifiedName() + else qualifier = this.getNamespace().getQualifiedName() } /** Gets the namespace containing this type. */ Namespace getNamespace() { - if exists(this.getDeclaringType()) then - result = this.getDeclaringType().getNamespace() - else - result.getATypeDeclaration() = this + if exists(this.getDeclaringType()) + then result = this.getDeclaringType().getNamespace() + else result.getATypeDeclaration() = this } - override Namespace getDeclaringNamespace() { - this = result.getATypeDeclaration() - } + override Namespace getDeclaringNamespace() { this = result.getATypeDeclaration() } override ValueOrRefType getDeclaringType() { none() } override string getUndecoratedName() { - if - this.getName().indexOf("<")>0 + if this.getName().indexOf("<") > 0 then - exists(string name, int p | name = this.getName() and p = min(int p2 | p2 = name.indexOf("<") and p2>0) | result=name.substring(0, p)) - else - result = this.getName() + exists(string name, int p | + name = this.getName() and p = min(int p2 | p2 = name.indexOf("<") and p2 > 0) + | + result = name.substring(0, p) + ) + else result = this.getName() } /** Gets a nested child type, if any. */ - NestedType getAChildType() { nested_types(result,this,_) } + NestedType getAChildType() { nested_types(result, this, _) } /** * Gets the source namespace declaration in which this type is declared, if any. @@ -108,7 +100,9 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * } * ``` */ - NamespaceDeclaration getParentNamespaceDeclaration() { parent_namespace_declaration(this,result) } + NamespaceDeclaration getParentNamespaceDeclaration() { + parent_namespace_declaration(this, result) + } /** Gets the immediate base class of this class, if any. */ Class getBaseClass() { extend(this, getTypeRef(result)) } @@ -222,8 +216,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ } private predicate hasNonOverriddenMember(Member m) { - isNonOverridden(m) - and + isNonOverridden(m) and ( m = getAMember() or @@ -241,7 +234,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ not memberOverrides(v) } - pragma [noinline] // Predicate folding for proper join-order + // Predicate folding for proper join-order + pragma[noinline] private predicate memberOverrides(Virtualizable v) { getAMember().(Virtualizable).getOverridee() = v } @@ -280,25 +274,21 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ StaticConstructor getStaticConstructor() { result = getAMember() } /** Gets a nested type of this type, if any. */ - NestedType getANestedType() { result = getAMember() } + NestedType getANestedType() { result = getAMember() } /** Gets the number of types that directly depend on this type. */ - int getAfferentCoupling() { - afferentCoupling(this, result) - } + int getAfferentCoupling() { afferentCoupling(this, result) } /** Gets the number of types that this type directly depends upon. */ - int getEfferentCoupling() { - efferentCoupling(this, result) - } + int getEfferentCoupling() { efferentCoupling(this, result) } /** Gets the length of *some* path to the root of the hierarchy. */ int getADepth() { - (this.hasQualifiedName("System", "Object") and result = 0) + this.hasQualifiedName("System", "Object") and result = 0 or - (result = this.getABaseType().getADepth() + 1 - //prevent recursion on cyclic inheritance (only for incorrect databases) - and not (this = this.getABaseType+())) + result = this.getABaseType().getADepth() + 1 and + //prevent recursion on cyclic inheritance (only for incorrect databases) + not this = this.getABaseType+() } /** @@ -306,14 +296,10 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * `object` in the type hierarchy. Types that are very deeply nested * may be difficult to maintain. */ - int getInheritanceDepth() { - result = max(this.getADepth()) - } + int getInheritanceDepth() { result = max(this.getADepth()) } /** Gets the number of (direct or indirect) base types. */ - int getNumberOfAncestors() { - result = count(this.getABaseType+()) - } + int getNumberOfAncestors() { result = count(this.getABaseType+()) } /** * Gets the Henderson-Sellers lack of cohesion metric. @@ -325,9 +311,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * Types with a high Henderson-Sellers metric have methods * which access many fields, and can be a maintainability problem. */ - float getLackOfCohesionHS() { - lackOfCohesionHS(this, result) - } + float getLackOfCohesionHS() { lackOfCohesionHS(this, result) } /** * Gets the Chidamber and Kemerer lack of cohesion metric. @@ -340,9 +324,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * Types with a high Chidamber and Kemerer metric have multiple * responsibilities so could be refactored. */ - float getLackOfCohesionCK() { - lackOfCohesionCK(this, result) - } + float getLackOfCohesionCK() { lackOfCohesionCK(this, result) } /** * Gets the *response* of this type, which is defined as the total number @@ -351,18 +333,17 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ */ int getResponse() { result = sum(Callable c | - c.getDeclaringType() = this | - count(Call call | - call.getEnclosingCallable() = c and - not call instanceof MemberAccess // property, indexer, and event accesses are not counted + c.getDeclaringType() = this + | + count(Call call | + call.getEnclosingCallable() = c and + not call instanceof MemberAccess // property, indexer, and event accesses are not counted + ) ) - ) } /** Gets the number of callables in this type. */ - int getNumberOfCallables() { - result = count(Callable c | this.getAMember() = c) - } + int getNumberOfCallables() { result = count(Callable c | this.getAMember() = c) } override ValueOrRefType getSourceDeclaration() { result = this and @@ -371,7 +352,7 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ // We must use `nested_types` here, rather than overriding `getSourceDeclaration` // in the class `NestedType` below. Otherwise, the overrides in `UnboundGenericType` // and its subclasses will not work - nested_types(this,_,result) + nested_types(this, _, result) } override string toString() { result = Type.super.toString() } @@ -391,18 +372,16 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_ * ``` */ class NestedType extends ValueOrRefType { + NestedType() { nested_types(this, _, _) } - NestedType() { nested_types(this,_,_) } - - override ValueOrRefType getDeclaringType() { nested_types(this,result,_) } + override ValueOrRefType getDeclaringType() { nested_types(this, result, _) } } /** * A non-nested type, that is declared directly in a namespace. */ class NonNestedType extends ValueOrRefType { - - NonNestedType() { exists(Namespace n | parent_namespace(this,n)) } + NonNestedType() { exists(Namespace n | parent_namespace(this, n)) } } /** @@ -437,7 +416,6 @@ class ValueType extends ValueOrRefType, @value_type { } * (`FloatingPointType`), or a decimal type (`DecimalType`). */ class SimpleType extends ValueType, @simple_type { - /** Gets the minimum integral value of this type, if any. */ int minValue() { none() } @@ -451,7 +429,6 @@ class SimpleType extends ValueType, @simple_type { * The Boolean type, `bool`. */ class BoolType extends SimpleType, @bool_type { - override string toStringWithTypes() { result = "bool" } } @@ -459,12 +436,11 @@ class BoolType extends SimpleType, @bool_type { * The Unicode character type, `char`. */ class CharType extends SimpleType, @char_type { - override string toStringWithTypes() { result = "char" } - override int minValue() { result=0 } + override int minValue() { result = 0 } - override int maxValue() { result=65535 } + override int maxValue() { result = 65535 } } /** @@ -473,8 +449,7 @@ class CharType extends SimpleType, @char_type { * Either a signed integral type (`SignedIntegralType`) or an unsigned integral type * (`UnsignedIntegralType`). */ -class IntegralType extends SimpleType, @integral_type { -} +class IntegralType extends SimpleType, @integral_type { } /** * An unsigned integral type. @@ -483,8 +458,7 @@ class IntegralType extends SimpleType, @integral_type { * or a `ulong` (`ULongType`). */ class UnsignedIntegralType extends IntegralType, @unsigned_integral_type { - - override int minValue() { result=0 } + override int minValue() { result = 0 } } /** @@ -493,50 +467,45 @@ class UnsignedIntegralType extends IntegralType, @unsigned_integral_type { * Either an `sbyte` (`SByteType`), a `short` (`ShortType`), an `int` * (`IntType`), or a `long` (`LongType`). */ -class SignedIntegralType extends IntegralType, @signed_integral_type { -} +class SignedIntegralType extends IntegralType, @signed_integral_type { } /** * The signed byte type, `sbyte`. */ class SByteType extends SignedIntegralType, @sbyte_type { - override string toStringWithTypes() { result = "sbyte" } - override int minValue() { result=-128 } + override int minValue() { result = -128 } - override int maxValue() { result=127 } + override int maxValue() { result = 127 } } /** * The `short` type. */ class ShortType extends SignedIntegralType, @short_type { - override string toStringWithTypes() { result = "short" } - override int minValue() { result=-32768 } + override int minValue() { result = -32768 } - override int maxValue() { result=32767 } + override int maxValue() { result = 32767 } } /** * The `int` type. */ class IntType extends SignedIntegralType, @int_type { - override string toStringWithTypes() { result = "int" } - override int minValue() { result=-2147483647-1 } + override int minValue() { result = -2147483647 - 1 } - override int maxValue() { result=2147483647 } + override int maxValue() { result = 2147483647 } } /** * The `long` type. */ class LongType extends SignedIntegralType, @long_type { - override string toStringWithTypes() { result = "long" } } @@ -545,7 +514,8 @@ class LongType extends SignedIntegralType, @long_type { */ class ByteType extends UnsignedIntegralType, @byte_type { override string toStringWithTypes() { result = "byte" } - override int maxValue() { result=255 } + + override int maxValue() { result = 255 } } /** @@ -553,14 +523,14 @@ class ByteType extends UnsignedIntegralType, @byte_type { */ class UShortType extends UnsignedIntegralType, @ushort_type { override string toStringWithTypes() { result = "ushort" } - override int maxValue() { result=65535 } + + override int maxValue() { result = 65535 } } /** * The unsigned int type, `uint`. */ class UIntType extends UnsignedIntegralType, @uint_type { - override string toStringWithTypes() { result = "uint" } } @@ -568,7 +538,6 @@ class UIntType extends UnsignedIntegralType, @uint_type { * The unsigned long type, `ulong`. */ class ULongType extends UnsignedIntegralType, @ulong_type { - override string toStringWithTypes() { result = "ulong" } } @@ -577,14 +546,12 @@ class ULongType extends UnsignedIntegralType, @ulong_type { * * Either a `float` (`FloatType`) or a `double` (`DoubleType`). */ -class FloatingPointType extends SimpleType, @floating_point_type { -} +class FloatingPointType extends SimpleType, @floating_point_type { } /** * The `float` type. */ class FloatType extends FloatingPointType, @float_type { - override string toStringWithTypes() { result = "float" } } @@ -592,7 +559,6 @@ class FloatType extends FloatingPointType, @float_type { * The `double` type. */ class DoubleType extends FloatingPointType, @double_type { - override string toStringWithTypes() { result = "double" } } @@ -600,7 +566,6 @@ class DoubleType extends FloatingPointType, @double_type { * The high-precision decimal type, `decimal`. */ class DecimalType extends SimpleType, @decimal_type { - override string toStringWithTypes() { result = "decimal" } } @@ -615,7 +580,6 @@ class DecimalType extends SimpleType, @decimal_type { * ``` */ class Enum extends ValueType, @enum_type { - /** * Gets the underlying integral type of this enum, not to be confused with * its base type which is always `System.Enum`. @@ -673,16 +637,13 @@ class Struct extends ValueType, @struct_type { * `null` (`NullType`), `dynamic` (`DynamicType`), or an array (`ArrayType`). */ class RefType extends ValueOrRefType, @ref_type { - /** Gets the number of overridden methods (NORM) of this reference type. */ - int getNumberOverridden() { - result = count(this.getAnOverrider()) - } + int getNumberOverridden() { result = count(this.getAnOverrider()) } /** Gets a member that overrides a non-abstract member in a super type, if any. */ private Virtualizable getAnOverrider() { - getAMember() = result and - exists(Virtualizable v | result.getOverridee() = v and not v.isAbstract()) + getAMember() = result and + exists(Virtualizable v | result.getOverridee() = v and not v.isAbstract()) } /** @@ -694,18 +655,14 @@ class RefType extends ValueOrRefType, @ref_type { * This measures the inheritance complexity of this type. */ float getSpecialisationIndex() { - this.getNumberOfCallables() != 0 - and - result = (this.getNumberOverridden() * this.getInheritanceDepth()) - / - ((float)this.getNumberOfCallables()) + this.getNumberOfCallables() != 0 and + result = (this.getNumberOverridden() * this.getInheritanceDepth()) / + this.getNumberOfCallables().(float) } } // Helper predicate to avoid slow "negation_body" -private predicate isNonOverridden(Member m) { - not m.(Virtualizable).isOverridden() -} +private predicate isNonOverridden(Member m) { not m.(Virtualizable).isOverridden() } /** * A `class`, for example @@ -716,8 +673,7 @@ private predicate isNonOverridden(Member m) { * } * ``` */ -class Class extends RefType, @class_type { -} +class Class extends RefType, @class_type { } /** * A class generated by the compiler from an anonymous object creation. @@ -728,15 +684,12 @@ class Class extends RefType, @class_type { * new { X = 0, Y = 0 }; * ``` */ -class AnonymousClass extends Class { - AnonymousClass() { this.getName().matches("<%") } -} +class AnonymousClass extends Class { AnonymousClass() { this.getName().matches("<%") } } /** * The `object` type, `System.Object`. */ class ObjectType extends Class { - ObjectType() { this.hasQualifiedName("System.Object") } override string toStringWithTypes() { result = "object" } @@ -746,7 +699,6 @@ class ObjectType extends Class { * The `string` type, `System.String`. */ class StringType extends Class { - StringType() { this.hasQualifiedName("System.String") } override string toStringWithTypes() { result = "string" } @@ -761,9 +713,7 @@ class StringType extends Class { * } * ``` */ -class Interface extends RefType, @interface_type { - -} +class Interface extends RefType, @interface_type { } /** * A `delegate` type, for example @@ -774,7 +724,7 @@ class Interface extends RefType, @interface_type { */ class DelegateType extends RefType, Parameterizable, @delegate_type { /** Gets the return type of this delegate. */ - Type getReturnType() { delegate_return_type(this,getTypeRef(result)) } + Type getReturnType() { delegate_return_type(this, getTypeRef(result)) } /** Holds if this delegate returns a `ref`. */ predicate returnsRef() { ref_returns(this) } @@ -792,46 +742,42 @@ class NullType extends RefType, @null_type { } * A nullable type, for example `int?`. */ class NullableType extends ValueType, DotNet::ConstructedGeneric, @nullable_type { - /** * Gets the underlying value type of this nullable type. * For example `int` in `int?`. */ - Type getUnderlyingType() { nullable_underlying_type(this,getTypeRef(result)) } + Type getUnderlyingType() { nullable_underlying_type(this, getTypeRef(result)) } - override string toStringWithTypes() { - result = getUnderlyingType().toStringWithTypes() + "?" - } + override string toStringWithTypes() { result = getUnderlyingType().toStringWithTypes() + "?" } override Type getChild(int n) { result = getUnderlyingType() and n = 0 } override Location getALocation() { result = getUnderlyingType().getALocation() } - override Type getTypeArgument(int p) { p=0 and result = getUnderlyingType() } + override Type getTypeArgument(int p) { p = 0 and result = getUnderlyingType() } } /** * An array type, for example `int[]`. */ class ArrayType extends DotNet::ArrayType, RefType, @array_type { - /** * Gets the dimension of this array type. For example `int[][]` is of * dimension 2, while `int[]` is of dimension 1. */ - int getDimension() { array_element_type(this,result,_,_) } + int getDimension() { array_element_type(this, result, _, _) } /** * Gets the rank of this array type. For example `int[,]` is of * rank 2, while `int[]` is of rank 1. */ - int getRank() { array_element_type(this,_,result,_) } + int getRank() { array_element_type(this, _, result, _) } /** Holds if this array is multi-dimensional. */ predicate isMultiDimensional() { this.getRank() > 1 } /** Gets the element type of this array, for example `int` in `int[]`. */ - override Type getElementType() { array_element_type(this,_,_,getTypeRef(result)) } + override Type getElementType() { array_element_type(this, _, _, getTypeRef(result)) } /** Holds if this array type has the same shape (dimension and rank) as `that` array type. */ predicate hasSameShapeAs(ArrayType that) { @@ -840,23 +786,19 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { } private string getRankString(int i) { - i in [0 .. getRank() - 1] - and - if i = getRank() - 1 then - result = "" - else ( - result = "," + getRankString(i + 1) - ) + i in [0 .. getRank() - 1] and + if i = getRank() - 1 then result = "" else result = "," + getRankString(i + 1) } private string getDimensionString(Type elementType) { exists(Type et, string res | et = getElementType() and res = "[" + getRankString(0) + "]" and - if et instanceof ArrayType then - result = res + et.(ArrayType).getDimensionString(elementType) - else - (result = res and elementType = et) + if et instanceof ArrayType + then result = res + et.(ArrayType).getDimensionString(elementType) + else ( + result = res and elementType = et + ) ) } @@ -880,7 +822,7 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { * A pointer type, for example `char*`. */ class PointerType extends DotNet::PointerType, Type, @pointer_type { - override Type getReferentType() { pointer_referent_type(this,getTypeRef(result)) } + override Type getReferentType() { pointer_referent_type(this, getTypeRef(result)) } override string toStringWithTypes() { result = DotNet::PointerType.super.toStringWithTypes() } @@ -897,7 +839,6 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type { * The `dynamic` type. */ class DynamicType extends RefType, @dynamic_type { - override string toStringWithTypes() { result = "dynamic" } } @@ -905,7 +846,6 @@ class DynamicType extends RefType, @dynamic_type { * The `__arglist` type, modeling varargs invocation in C++. */ class ArglistType extends Type, @arglist_type { - override string toStringWithTypes() { result = "__arglist" } } @@ -913,55 +853,48 @@ class ArglistType extends Type, @arglist_type { * A type that could not be resolved. This could happen if an indirect reference * is not available at compilation time. */ -class UnknownType extends Type, @unknown_type { -} +class UnknownType extends Type, @unknown_type { } /** * A type representing a tuple. For example, `(int, bool, string)`. */ class TupleType extends ValueType, @tuple_type { - /** Gets the underlying type of this tuple, which is of type `System.ValueTuple`. */ - ConstructedStruct getUnderlyingType() { - tuple_underlying_type(this, result) - } + ConstructedStruct getUnderlyingType() { tuple_underlying_type(this, result) } /** * Gets the `n`th element of this tuple, indexed from 0. * For example, the 0th (first) element of `(int, string)` is the field `Item1 int`. */ - Field getElement(int n) { - tuple_element(this, n, result) - } + Field getElement(int n) { tuple_element(this, n, result) } /** * Gets the type of the `n`th element of this tuple, indexed from 0. * For example, the 0th (first) element type of `(int, string)` is `int`. */ - Type getElementType(int n) { - result = getElement(n).getType() - } + Type getElementType(int n) { result = getElement(n).getType() } /** Gets an element of this tuple. */ - Field getAnElement() { - result = getElement(_) - } + Field getAnElement() { result = getElement(_) } - override Location getALocation() { - type_location(this, result) - } + override Location getALocation() { type_location(this, result) } /** * Gets the arity of this tuple. For example, the arity of * `(int, int, double)` is 3. */ - int getArity() { - result=count(getAnElement()) - } + int getArity() { result = count(getAnElement()) } - language [monotonicAggregates] + language[monotonicAggregates] override string toStringWithTypes() { - result = "(" + concat(int i | exists(getElement(i)) | getElement(i).getType().toStringWithTypes(), ", " order by i) + ")" + result = "(" + + concat(int i | + exists(getElement(i)) + | + getElement(i).getType().toStringWithTypes(), ", " + order by + i + ) + ")" } override string getLabel() { result = getUnderlyingType().getLabel() } @@ -973,6 +906,7 @@ class TupleType extends ValueType, @tuple_type { */ class TypeMention extends @type_mention { Type type; + @type_mention_parent parent; TypeMention() { type_mention(this, getTypeRef(type), parent) } diff --git a/csharp/ql/src/semmle/code/csharp/Using.qll b/csharp/ql/src/semmle/code/csharp/Using.qll index 35687e39496..9b1362cf9dc 100644 --- a/csharp/ql/src/semmle/code/csharp/Using.qll +++ b/csharp/ql/src/semmle/code/csharp/Using.qll @@ -34,9 +34,7 @@ class UsingDirective extends Element, @using_directive { parent_namespace_declaration(this, result) } - override Location getALocation() { - using_directive_location(this, result) - } + override Location getALocation() { using_directive_location(this, result) } } /** @@ -47,7 +45,7 @@ class UsingNamespaceDirective extends UsingDirective, @using_namespace_directive * Gets the target of this namespace `using` directive, for example `System` * in `using System`. */ - Namespace getImportedNamespace() { using_namespace_directives(this,result) } + Namespace getImportedNamespace() { using_namespace_directives(this, result) } override string toString() { result = "using ...;" } } @@ -60,9 +58,7 @@ class UsingStaticDirective extends UsingDirective, @using_static_directive { * Gets the target of this type `using` directive, for example * `System.Console` in `using static System.Console`. */ - ValueOrRefType getTarget() { - using_static_directives(this, getTypeRef(result)) - } + ValueOrRefType getTarget() { using_static_directives(this, getTypeRef(result)) } override string toString() { result = "using static ...;" } } diff --git a/csharp/ql/src/semmle/code/csharp/Variable.qll b/csharp/ql/src/semmle/code/csharp/Variable.qll index 712e4638167..38794fe9ac2 100644 --- a/csharp/ql/src/semmle/code/csharp/Variable.qll +++ b/csharp/ql/src/semmle/code/csharp/Variable.qll @@ -14,46 +14,56 @@ private import semmle.code.csharp.ExprOrStmtParent * A variable. Either a variable with local scope (`LocalScopeVariable`) or a field (`Field`). */ class Variable extends Assignable, DotNet::Variable, @variable { - /** Gets the type that declares this variable, if any. */ override ValueOrRefType getDeclaringType() { - fields(this,_,_,result,_,_) or - exists(Expr e | localvars(this, _, _, _, _, e) and result = e.getEnclosingStmt().getEnclosingCallable().getDeclaringType()) or - exists(Callable parent | params(this, _, _, _, _ , parent, _) and result = parent.getDeclaringType()) or - exists(Indexer indexer | params(this, _, _, _, _, indexer, _) and result = indexer.getDeclaringType()) or - exists(@delegate_type t | params(this, _, _, _, _, t, _) and result = t) or - exists(Expr parent | params(this, _, _, _, _, parent, _) and result = parent.getEnclosingCallable().getDeclaringType()) + fields(this, _, _, result, _, _) + or + exists(Expr e | + localvars(this, _, _, _, _, e) and + result = e.getEnclosingStmt().getEnclosingCallable().getDeclaringType() + ) + or + exists(Callable parent | + params(this, _, _, _, _, parent, _) and result = parent.getDeclaringType() + ) + or + exists(Indexer indexer | + params(this, _, _, _, _, indexer, _) and result = indexer.getDeclaringType() + ) + or + exists(@delegate_type t | params(this, _, _, _, _, t, _) and result = t) + or + exists(Expr parent | + params(this, _, _, _, _, parent, _) and + result = parent.getEnclosingCallable().getDeclaringType() + ) } override Variable getSourceDeclaration() { result = this } override string getName() { - params(this,result,_,_,_,_,_) or - localvars(this,_,result,_,_,_) or - fields(this,_,result,_,_,_) + params(this, result, _, _, _, _, _) or + localvars(this, _, result, _, _, _) or + fields(this, _, result, _, _, _) } /** Gets the type of this variable. For example `int` in `int x`. */ override Type getType() { - params(this,_,getTypeRef(result),_,_,_,_) or - localvars(this,_,_,_,getTypeRef(result),_) or - fields(this,_,_,_,getTypeRef(result),_) + params(this, _, getTypeRef(result), _, _, _, _) or + localvars(this, _, _, _, getTypeRef(result), _) or + fields(this, _, _, _, getTypeRef(result), _) } override Location getALocation() { - param_location(this,result) or - localvar_location(this,result) or - field_location(this,result) + param_location(this, result) or + localvar_location(this, result) or + field_location(this, result) } - override VariableAccess getAnAccess() { - result.getTarget() = this - } + override VariableAccess getAnAccess() { result.getTarget() = this } /** Gets the expression used to initialise this variable, if any. */ - Expr getInitializer() { - none() - } + Expr getInitializer() { none() } } /** @@ -77,9 +87,7 @@ class LocalScopeVariable extends Variable, @local_scope_variable { * } * ``` */ - predicate isCaptured() { - exists(this.getACapturingCallable()) - } + predicate isCaptured() { exists(this.getACapturingCallable()) } /** * Gets a callable that captures this variable, if any. For example, @@ -115,8 +123,8 @@ class LocalScopeVariable extends Variable, @local_scope_variable { * } * ``` */ -class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, TopLevelExprParent, @parameter { - +class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, TopLevelExprParent, + @parameter { /** * Gets the position of this parameter. For example, the position of `x` is * 0 and the position of `y` is 1 in @@ -127,7 +135,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - override int getPosition() { params(this,_,_,result,_,_,_) } + override int getPosition() { params(this, _, _, result, _, _, _) } override int getIndex() { result = this.getPosition() } @@ -141,7 +149,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - predicate isValue() { params(this,_,_,_,0,_,_) } + predicate isValue() { params(this, _, _, _, 0, _, _) } /** * Holds if this parameter is a reference parameter. For example, `p` @@ -153,7 +161,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - override predicate isRef() { params(this,_,_,_,1,_,_) } + override predicate isRef() { params(this, _, _, _, 1, _, _) } /** * Holds if this parameter is an output parameter. For example, `p` @@ -165,7 +173,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - override predicate isOut() { params(this,_,_,_,2,_,_) } + override predicate isOut() { params(this, _, _, _, 2, _, _) } /** * Holds if this parameter is a value type that is passed in by reference. @@ -177,7 +185,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - predicate isIn() { params(this,_,_,_,5,_,_) } + predicate isIn() { params(this, _, _, _, 5, _, _) } /** Holds if this parameter is an output or reference parameter. */ predicate isOutOrRef() { isOut() or isRef() } @@ -192,7 +200,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - predicate isParams() { params(this,_,_,_,3,_,_) } + predicate isParams() { params(this, _, _, _, 3, _, _) } /** * Holds this parameter is the first parameter of an extension method. @@ -205,12 +213,12 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * } * ``` */ - predicate hasExtensionMethodModifier() { params(this,_,_,_,4,_,_) } + predicate hasExtensionMethodModifier() { params(this, _, _, _, 4, _, _) } /** Gets the declaring element of this parameter. */ - Parameterizable getDeclaringElement() { params(this,_,_,_,_,result,_) } + Parameterizable getDeclaringElement() { params(this, _, _, _, _, result, _) } - override Parameter getSourceDeclaration() { params(this,_,_,_,_,_,result) } + override Parameter getSourceDeclaration() { params(this, _, _, _, _, _, result) } override string toString() { result = this.getName() } @@ -232,9 +240,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top predicate hasDefaultValue() { exists(getDefaultValue()) } /** Gets the callable to which this parameter belongs, if any. */ - override Callable getCallable() { - result.getAParameter() = this - } + override Callable getCallable() { result.getAParameter() = this } /** * Gets an argument which is assigned to this parameter in a call to the @@ -258,9 +264,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top * The assigned arguments to `x` are `1` and `4`, the assigned argument to * `y` is `5`, and the assigned arguments to `z` are `3` and `6`, respectively. */ - Expr getAnAssignedArgument() { - result = getCallable().getACall().getArgumentForParameter(this) - } + Expr getAnAssignedArgument() { result = getCallable().getACall().getArgumentForParameter(this) } /** Holds if this parameter is potentially overwritten in the body of its callable. */ predicate isOverwritten() { @@ -310,7 +314,6 @@ class ImplicitAccessorParameter extends Parameter { * ``` */ class LocalVariable extends LocalScopeVariable, @local_variable { - /** Gets the declaration of this local variable. */ LocalVariableDeclExpr getVariableDeclExpr() { result.getVariable() = this } @@ -343,16 +346,14 @@ class LocalVariable extends LocalScopeVariable, @local_variable { * } * ``` */ - predicate isImplicitlyTyped() { localvars(this,_,_,1,_,_) } + predicate isImplicitlyTyped() { localvars(this, _, _, 1, _, _) } /** Gets the enclosing callable of this local variable. */ - Callable getEnclosingCallable() { - result = this.getVariableDeclExpr().getEnclosingCallable() - } + Callable getEnclosingCallable() { result = this.getVariableDeclExpr().getEnclosingCallable() } override Callable getCallable() { result = getEnclosingCallable() } - override predicate isRef() { localvars(this,3,_,_,_,_) } + override predicate isRef() { localvars(this, 3, _, _, _, _) } } /** @@ -367,7 +368,6 @@ class LocalVariable extends LocalScopeVariable, @local_variable { * ``` */ class LocalConstant extends LocalVariable, @local_constant { - /** Gets the declaration of this local constant. */ override LocalConstantDeclExpr getVariableDeclExpr() { result.getVariable() = this } @@ -384,7 +384,8 @@ class LocalConstant extends LocalVariable, @local_constant { * } * ``` */ -class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent, DotNet::Field, @field { +class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent, DotNet::Field, + @field { /** Gets the initializer of this field, if any. */ override Expr getInitializer() { result = this.getChildExpr(0) } @@ -394,7 +395,7 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent /** Holds if this field is `readonly`. */ predicate isReadOnly() { this.hasModifier("readonly") } - override Field getSourceDeclaration() { fields(this,_,_,_,_,result) } + override Field getSourceDeclaration() { fields(this, _, _, _, _, result) } override FieldAccess getAnAccess() { result = Variable.super.getAnAccess() } @@ -415,7 +416,6 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent * ``` */ class MemberConstant extends Field, @constant { - /** Gets the computed value of this constant. */ string getValue() { constant_value(this, result) } } @@ -431,7 +431,6 @@ class MemberConstant extends Field, @constant { * ``` */ class EnumConstant extends MemberConstant { - EnumConstant() { this.getDeclaringType() instanceof Enum } /** Gets the `enum` that declares this constant. */ @@ -448,9 +447,7 @@ class EnumConstant extends MemberConstant { * } * ``` */ - IntegralType getUnderlyingType() { - result = this.getDeclaringEnum().getUnderlyingType() - } + IntegralType getUnderlyingType() { result = this.getDeclaringEnum().getUnderlyingType() } /** * Holds if this `enum` constant has an explicit value. If not, diff --git a/csharp/ql/src/semmle/code/csharp/XML.qll b/csharp/ql/src/semmle/code/csharp/XML.qll index 18be5bbee1f..0a9227c9128 100644 --- a/csharp/ql/src/semmle/code/csharp/XML.qll +++ b/csharp/ql/src/semmle/code/csharp/XML.qll @@ -9,7 +9,7 @@ import semmle.code.csharp.Location library class XMLLocatableElement extends @xmllocatable, Element { override string toString() { result = this.(XMLLocatable).toString() } - override Location getALocation() { result = this.(XMLLocatable).getALocation() } + override Location getALocation() { result = this.(XMLLocatable).getALocation() } } /** An XML element that has a location. */ @@ -19,15 +19,17 @@ class XMLLocatable extends @xmllocatable { } /** Gets the source location for this element. */ - Location getALocation() { xmllocations(this,result) } + Location getALocation() { xmllocations(this, result) } /** * Whether this element has the specified location information, * including file path, start line, start column, end line and end column. */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { exists(File f, Location l | l = this.getALocation() | - locations_default(l,f,startline,startcolumn,endline,endcolumn) and + locations_default(l, f, startline, startcolumn, endline, endcolumn) and filepath = f.getAbsolutePath() ) } @@ -48,45 +50,45 @@ class XMLParent extends @xmlparent { abstract string getName(); /** Gets the file to which this XML parent belongs. */ - XMLFile getFile() { result = this or xmlElements(this,_,_,_,result) } + XMLFile getFile() { result = this or xmlElements(this, _, _, _, result) } /** Gets the child element at a specified index of this XML parent. */ XMLElement getChild(int index) { xmlElements(result, _, this, index, _) } /** Gets a child element of this XML parent. */ - XMLElement getAChild() { xmlElements(result,_,this,_,_) } + XMLElement getAChild() { xmlElements(result, _, this, _, _) } /** Gets a child element of this XML parent with the given `name`. */ - XMLElement getAChild(string name) { xmlElements(result,_,this,_,_) and result.hasName(name) } + XMLElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) } /** Gets a comment that is a child of this XML parent. */ - XMLComment getAComment() { xmlComments(result,_,this,_) } + XMLComment getAComment() { xmlComments(result, _, this, _) } /** Gets a character sequence that is a child of this XML parent. */ - XMLCharacters getACharactersSet() { xmlChars(result,_,this,_,_,_) } + XMLCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) } /** Gets the depth in the tree. (Overridden in XMLElement.) */ int getDepth() { result = 0 } /** Gets the number of child XML elements of this XML parent. */ - int getNumberOfChildren() { - result = count(XMLElement e | xmlElements(e,_,this,_,_)) - } + int getNumberOfChildren() { result = count(XMLElement e | xmlElements(e, _, this, _, _)) } /** Gets the number of places in the body of this XML parent where text occurs. */ - int getNumberOfCharacterSets() { - result = count(int pos | xmlChars(_,_,this,pos,_,_)) - } + int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) } /** Append all the character sequences of this XML parent from left to right, separated by a space. */ string allCharactersString() { - result = concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos) + result = concat(string chars, int pos | + xmlChars(_, chars, this, pos, _, _) + | + chars, " " + order by + pos + ) } /** Gets the text value contained in this XML parent. */ - string getTextValue() { - result = allCharactersString() - } + string getTextValue() { result = allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -94,63 +96,59 @@ class XMLParent extends @xmlparent { /** An XML file. */ class XMLFile extends XMLParent, File { - XMLFile() { - xmlEncoding(this,_) - } + XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ override string toString() { result = XMLParent.super.toString() } /** Gets the name of this XML file. */ - override string getName() { files(this,result,_,_,_) } + override string getName() { files(this, result, _, _, _) } /** Gets the path of this XML file. */ - string getPath() { files(this,_,result,_,_) } + string getPath() { files(this, _, result, _, _) } /** Gets the path of the folder that contains this XML file. */ string getFolder() { - result = this.getPath().substring(0, this.getPath().length()-this.getName().length()) + result = this.getPath().substring(0, this.getPath().length() - this.getName().length()) } /** Gets the encoding of this XML file. */ - string getEncoding() { xmlEncoding(this,result) } + string getEncoding() { xmlEncoding(this, result) } /** Gets the XML file itself. */ - override - XMLFile getFile() { result = this } + override XMLFile getFile() { result = this } /** Gets a top-most element in an XML file. */ XMLElement getARootElement() { result = this.getAChild() } /** Gets a DTD associated with this XML file. */ - XMLDTD getADTD() { xmlDTDs(result,_,_,_,this) } + XMLDTD getADTD() { xmlDTDs(result, _, _, _, this) } } /** A "Document Type Definition" of an XML file. */ class XMLDTD extends XMLLocatable, @xmldtd { /** Gets the name of the root element of this DTD. */ - string getRoot() { xmlDTDs(this,result,_,_,_) } + string getRoot() { xmlDTDs(this, result, _, _, _) } /** Gets the public ID of this DTD. */ - string getPublicId() { xmlDTDs(this,_,result,_,_) } + string getPublicId() { xmlDTDs(this, _, result, _, _) } /** Gets the system ID of this DTD. */ - string getSystemId() { xmlDTDs(this,_,_,result,_) } + string getSystemId() { xmlDTDs(this, _, _, result, _) } /** Holds if this DTD is public. */ - predicate isPublic() { not xmlDTDs(this,_,"",_,_) } + predicate isPublic() { not xmlDTDs(this, _, "", _, _) } /** Gets the parent of this DTD. */ - XMLParent getParent() { xmlDTDs(this,_,_,_,result) } + XMLParent getParent() { xmlDTDs(this, _, _, _, result) } /** Gets a printable representation of this DTD. */ override string toString() { - (this.isPublic() and result = this.getRoot() + " PUBLIC '" + - this.getPublicId() + "' '" + - this.getSystemId() + "'") or - (not this.isPublic() and result = this.getRoot() + - " SYSTEM '" + - this.getSystemId() + "'") + this.isPublic() and + result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'" + or + not this.isPublic() and + result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'" } } @@ -160,48 +158,40 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { predicate hasName(string name) { name = getName() } /** Gets the name of this XML element. */ - override string getName() { xmlElements(this,result,_,_,_) } + override string getName() { xmlElements(this, result, _, _, _) } /** Gets the XML file in which this XML element occurs. */ - override - XMLFile getFile() { xmlElements(this,_,_,_,result) } + override XMLFile getFile() { xmlElements(this, _, _, _, result) } /** Gets the parent of this XML element. */ - XMLParent getParent() { xmlElements(this,_,result,_,_) } + XMLParent getParent() { xmlElements(this, _, result, _, _) } /** Gets the index of this XML element among its parent's children. */ int getIndex() { xmlElements(this, _, _, result, _) } /** Holds if this XML element has a namespace. */ - predicate hasNamespace() { xmlHasNs(this,_,_) } + predicate hasNamespace() { xmlHasNs(this, _, _) } /** Gets the namespace of this XML element, if any. */ - XMLNamespace getNamespace() { xmlHasNs(this,result,_) } + XMLNamespace getNamespace() { xmlHasNs(this, result, _) } /** Gets the index of this XML element among its parent's children. */ - int getElementPositionIndex() { xmlElements(this,_,_,result,_) } + int getElementPositionIndex() { xmlElements(this, _, _, result, _) } /** Gets the depth of this element within the XML file tree structure. */ - override - int getDepth() { result = this.getParent().getDepth() + 1 } + override int getDepth() { result = this.getParent().getDepth() + 1 } /** Gets an XML attribute of this XML element. */ XMLAttribute getAnAttribute() { result.getElement() = this } /** Gets the attribute with the specified `name`, if any. */ - XMLAttribute getAttribute(string name) { - result.getElement() = this and result.getName() = name - } + 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(XMLAttribute a | a = this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ - string getAttributeValue(string name) { - result = this.getAttribute(name).getValue() - } + string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ override string toString() { result = XMLParent.super.toString() } @@ -210,19 +200,19 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { /** An attribute that occurs inside an XML element. */ class XMLAttribute extends @xmlattribute, XMLLocatable { /** Gets the name of this attribute. */ - string getName() { xmlAttrs(this,_,result,_,_,_) } + string getName() { xmlAttrs(this, _, result, _, _, _) } /** Gets the XML element to which this attribute belongs. */ - XMLElement getElement() { xmlAttrs(this,result,_,_,_,_) } + XMLElement getElement() { xmlAttrs(this, result, _, _, _, _) } /** Holds if this attribute has a namespace. */ - predicate hasNamespace() { xmlHasNs(this,_,_) } + predicate hasNamespace() { xmlHasNs(this, _, _) } /** Gets the namespace of this attribute, if any. */ - XMLNamespace getNamespace() { xmlHasNs(this,result,_) } + XMLNamespace getNamespace() { xmlHasNs(this, result, _) } /** Gets the value of this attribute. */ - string getValue() { xmlAttrs(this,_,_,result,_,_) } + string getValue() { xmlAttrs(this, _, _, result, _, _) } /** Gets a printable representation of this XML attribute. */ override string toString() { result = this.getName() + "=" + this.getValue() } @@ -231,27 +221,28 @@ class XMLAttribute extends @xmlattribute, XMLLocatable { /** A namespace used in an XML file */ class XMLNamespace extends XMLLocatable, @xmlnamespace { /** Gets the prefix of this namespace. */ - string getPrefix() { xmlNs(this,result,_,_) } + string getPrefix() { xmlNs(this, result, _, _) } /** Gets the URI of this namespace. */ - string getURI() { xmlNs(this,_,result,_) } + string getURI() { xmlNs(this, _, result, _) } /** Holds if this namespace has no prefix. */ predicate isDefault() { this.getPrefix() = "" } override string toString() { - (this.isDefault() and result = this.getURI()) or - (not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()) + this.isDefault() and result = this.getURI() + or + not this.isDefault() and result = this.getPrefix() + ":" + this.getURI() } } /** A comment of the form `` is an XML comment. */ class XMLComment extends @xmlcomment, XMLLocatable { /** Gets the text content of this XML comment. */ - string getText() { xmlComments(this,result,_,_) } + string getText() { xmlComments(this, result, _, _) } /** Gets the parent of this XML comment. */ - XMLParent getParent() { xmlComments(this,_,result,_) } + XMLParent getParent() { xmlComments(this, _, result, _) } /** Gets a printable representation of this XML comment. */ override string toString() { result = this.getText() } @@ -263,13 +254,13 @@ class XMLComment extends @xmlcomment, XMLLocatable { */ class XMLCharacters extends @xmlcharacters, XMLLocatable { /** Gets the content of this character sequence. */ - string getCharacters() { xmlChars(this,result,_,_,_,_) } + string getCharacters() { xmlChars(this, result, _, _, _, _) } /** Gets the parent of this character sequence. */ - XMLParent getParent() { xmlChars(this,_,result,_,_,_) } + XMLParent getParent() { xmlChars(this, _, result, _, _, _) } /** Holds if this character sequence is CDATA. */ - predicate isCDATA() { xmlChars(this,_,_,_,1,_) } + predicate isCDATA() { xmlChars(this, _, _, _, 1, _) } /** Gets a printable representation of this XML character sequence. */ override string toString() { result = this.getCharacters() } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll b/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll index f7f0183b1da..16f5671676c 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Assertions.qll @@ -1,4 +1,5 @@ /** Provides classes for assertions. */ + private import semmle.code.csharp.frameworks.system.Diagnostics private import semmle.code.csharp.frameworks.test.VisualStudio private import semmle.code.csharp.frameworks.System @@ -11,29 +12,23 @@ abstract class AssertMethod extends Method { abstract int getAssertionIndex(); /** Gets the parameter being asserted. */ - final Parameter getAssertedParameter() { - result = this.getParameter(this.getAssertionIndex()) - } + final Parameter getAssertedParameter() { result = this.getParameter(this.getAssertionIndex()) } /** Gets the exception being thrown if the assertion fails, if any. */ abstract ExceptionClass getExceptionClass(); } /** A positive assertion method. */ -abstract class AssertTrueMethod extends AssertMethod { -} +abstract class AssertTrueMethod extends AssertMethod { } /** A negated assertion method. */ -abstract class AssertFalseMethod extends AssertMethod { -} +abstract class AssertFalseMethod extends AssertMethod { } /** A `null` assertion method. */ -abstract class AssertNullMethod extends AssertMethod { -} +abstract class AssertNullMethod extends AssertMethod { } /** A non-`null` assertion method. */ -abstract class AssertNonNullMethod extends AssertMethod { -} +abstract class AssertNonNullMethod extends AssertMethod { } /** An assertion, that is, a call to an assertion method. */ class Assertion extends MethodCall { @@ -45,17 +40,14 @@ class Assertion extends MethodCall { AssertMethod getAssertMethod() { result = target } /** Gets the expression that this assertion pertains to. */ - Expr getExpr() { - result = this.getArgumentForParameter(target.getAssertedParameter()) - } + Expr getExpr() { result = this.getArgumentForParameter(target.getAssertedParameter()) } pragma[nomagic] private JoinBlockPredecessor getAPossiblyDominatedPredecessor(JoinBlock jb) { // Only calculate dominance by explicit recursion for split nodes; // all other nodes can use regular CFG dominance this instanceof ControlFlow::Internal::SplitControlFlowElement and - exists(BasicBlock bb | - bb = this.getAControlFlowNode().getBasicBlock() | + exists(BasicBlock bb | bb = this.getAControlFlowNode().getBasicBlock() | result = bb.getASuccessor*() ) and result.getASuccessor() = jb and @@ -65,8 +57,7 @@ class Assertion extends MethodCall { pragma[nomagic] private predicate isPossiblyDominatedJoinBlock(JoinBlock jb) { exists(this.getAPossiblyDominatedPredecessor(jb)) and - forall(BasicBlock pred | - pred = jb.getAPredecessor() | + forall(BasicBlock pred | pred = jb.getAPredecessor() | pred = this.getAPossiblyDominatedPredecessor(jb) or jb.dominates(pred) @@ -77,16 +68,15 @@ class Assertion extends MethodCall { private predicate strictlyDominatesSplit(BasicBlock bb) { this.getAControlFlowNode().getBasicBlock().immediatelyDominates(bb) or - if bb instanceof JoinBlock then + if bb instanceof JoinBlock + then this.isPossiblyDominatedJoinBlock(bb) and - forall(BasicBlock pred | - pred = this.getAPossiblyDominatedPredecessor(bb) | + forall(BasicBlock pred | pred = this.getAPossiblyDominatedPredecessor(bb) | this.strictlyDominatesSplit(pred) or this.getAControlFlowNode().getBasicBlock() = pred ) - else - this.strictlyDominatesSplit(bb.getAPredecessor()) + else this.strictlyDominatesSplit(bb.getAPredecessor()) } /** @@ -111,7 +101,8 @@ class FailingAssertion extends Assertion { FailingAssertion() { exists(AssertMethod am, Expr e | am = this.getAssertMethod() and - e = this.getExpr() | + e = this.getExpr() + | am instanceof AssertTrueMethod and e.getValue() = "false" or @@ -140,9 +131,7 @@ class SystemDiagnosticsDebugAssertTrueMethod extends AssertTrueMethod { /** A Visual Studio assertion method. */ class VSTestAssertTrueMethod extends AssertTrueMethod { - VSTestAssertTrueMethod() { - this = any(VSTestAssertClass c).getIsTrueMethod() - } + VSTestAssertTrueMethod() { this = any(VSTestAssertClass c).getIsTrueMethod() } override int getAssertionIndex() { result = 0 } @@ -151,9 +140,7 @@ class VSTestAssertTrueMethod extends AssertTrueMethod { /** A Visual Studio negated assertion method. */ class VSTestAssertFalseMethod extends AssertFalseMethod { - VSTestAssertFalseMethod() { - this = any(VSTestAssertClass c).getIsFalseMethod() - } + VSTestAssertFalseMethod() { this = any(VSTestAssertClass c).getIsFalseMethod() } override int getAssertionIndex() { result = 0 } @@ -162,9 +149,7 @@ class VSTestAssertFalseMethod extends AssertFalseMethod { /** A Visual Studio `null` assertion method. */ class VSTestAssertNullMethod extends AssertNullMethod { - VSTestAssertNullMethod() { - this = any(VSTestAssertClass c).getIsNullMethod() - } + VSTestAssertNullMethod() { this = any(VSTestAssertClass c).getIsNullMethod() } override int getAssertionIndex() { result = 0 } @@ -173,9 +158,7 @@ class VSTestAssertNullMethod extends AssertNullMethod { /** A Visual Studio non-`null` assertion method. */ class VSTestAssertNonNullMethod extends AssertNonNullMethod { - VSTestAssertNonNullMethod() { - this = any(VSTestAssertClass c).getIsNotNullMethod() - } + VSTestAssertNonNullMethod() { this = any(VSTestAssertClass c).getIsNotNullMethod() } override int getAssertionIndex() { result = 0 } @@ -185,13 +168,13 @@ class VSTestAssertNonNullMethod extends AssertNonNullMethod { /** A method that forwards to another assertion method. */ class ForwarderAssertMethod extends AssertMethod { Assertion a; + Parameter p; ForwarderAssertMethod() { p = this.getAParameter() and strictcount(AssignableDefinition def | def.getTarget() = p) = 1 and - forex(ControlFlowElement body | - body = this.getABody() | + forex(ControlFlowElement body | body = this.getABody() | bodyAsserts(this, body, a) and a.getExpr() = p.getAnAccess() ) @@ -227,33 +210,23 @@ private Stmt getAnAssertingStmt(Assertion a) { /** A method that forwards to a positive assertion method. */ class ForwarderAssertTrueMethod extends ForwarderAssertMethod, AssertTrueMethod { - ForwarderAssertTrueMethod() { - this.getUnderlyingAssertMethod() instanceof AssertTrueMethod - } + ForwarderAssertTrueMethod() { this.getUnderlyingAssertMethod() instanceof AssertTrueMethod } } /** A method that forwards to a negated assertion method. */ class ForwarderAssertFalseMethod extends ForwarderAssertMethod, AssertFalseMethod { - ForwarderAssertFalseMethod() { - this.getUnderlyingAssertMethod() instanceof AssertFalseMethod - } + ForwarderAssertFalseMethod() { this.getUnderlyingAssertMethod() instanceof AssertFalseMethod } } /** A method that forwards to a `null` assertion method. */ class ForwarderAssertNullMethod extends ForwarderAssertMethod, AssertNullMethod { - ForwarderAssertNullMethod() { - this.getUnderlyingAssertMethod() instanceof AssertNullMethod - } + ForwarderAssertNullMethod() { this.getUnderlyingAssertMethod() instanceof AssertNullMethod } } /** A method that forwards to a non-`null` assertion method. */ class ForwarderAssertNonNullMethod extends ForwarderAssertMethod, AssertNonNullMethod { - ForwarderAssertNonNullMethod() { - this.getUnderlyingAssertMethod() instanceof AssertNonNullMethod - } + ForwarderAssertNonNullMethod() { this.getUnderlyingAssertMethod() instanceof AssertNonNullMethod } } /** Holds if expression `e` appears in an assertion. */ -predicate isExprInAssertion(Expr e) { - e = any(Assertion a).getExpr().getAChildExpr*() -} +predicate isExprInAssertion(Expr e) { e = any(Assertion a).getExpr().getAChildExpr*() } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Collections.qll b/csharp/ql/src/semmle/code/csharp/commons/Collections.qll index ceabeb4f360..412b33a703b 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Collections.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Collections.qll @@ -1,4 +1,5 @@ /** Provides classes for collections. */ + import csharp private string modifyMethodName() { @@ -82,11 +83,13 @@ private string genericCollectionTypeName() { /** A collection type. */ class CollectionType extends RefType { CollectionType() { - exists(RefType base | - base = this.getABaseType*() | + exists(RefType base | base = this.getABaseType*() | base.hasQualifiedName(collectionNamespaceName(), collectionTypeName()) or - base.(ConstructedType).getUnboundGeneric().hasQualifiedName(genericCollectionNamespaceName(), genericCollectionTypeName()) + base + .(ConstructedType) + .getUnboundGeneric() + .hasQualifiedName(genericCollectionNamespaceName(), genericCollectionTypeName()) ) or this instanceof ArrayType @@ -138,10 +141,7 @@ private string noAddMethodName() { /** Holds if `a` is an access that does not modify a collection. */ private predicate readonlyAccess(Access a) { // A read-only method call - exists(MethodCall mc | - mc.getQualifier() = a | - mc.getTarget().hasName(readonlyMethodName()) - ) + exists(MethodCall mc | mc.getQualifier() = a | mc.getTarget().hasName(readonlyMethodName())) or // Any property access a = any(PropertyAccess pa).getQualifier() @@ -155,19 +155,14 @@ class NoAddAccess extends Access { NoAddAccess() { readonlyAccess(this) or - exists(MethodCall mc | - mc.getQualifier() = this | - mc.getTarget().hasName(noAddMethodName()) - ) + exists(MethodCall mc | mc.getQualifier() = this | mc.getTarget().hasName(noAddMethodName())) } } - /** An access that initializes an empty collection. */ class EmptyInitializationAccess extends Access { EmptyInitializationAccess() { - exists(AssignableDefinition def | - def.getTargetAccess() = this | + exists(AssignableDefinition def | def.getTargetAccess() = this | def.getSource() instanceof EmptyCollectionCreation ) } diff --git a/csharp/ql/src/semmle/code/csharp/commons/ComparisonTest.qll b/csharp/ql/src/semmle/code/csharp/commons/ComparisonTest.qll index 5bb2302c8f3..2247e522e9b 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/ComparisonTest.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/ComparisonTest.qll @@ -84,49 +84,44 @@ private newtype TComparisonTest = kind.isLessThanEquals() and first = co.getLeftOperand() and second = co.getRightOperand() - } - or + } or TEqualsCall(MethodCall mc) { - exists(Method m | - m = mc.getTarget() | + exists(Method m | m = mc.getTarget() | m instanceof EqualsMethod or m instanceof IEquatableEqualsMethod ) - } - or + } or TStaticEqualsCall(MethodCall mc) { - exists(Method m | - m = mc.getTarget() | + exists(Method m | m = mc.getTarget() | m = any(SystemObjectClass c).getStaticEqualsMethod() or m = any(SystemObjectClass c).getReferenceEqualsMethod() ) - } - or + } or TCompareToCall(MethodCall mc) { exists(Method m, Method target | target = mc.getTarget() and - (target = m or target = m.getAnUltimateImplementor()) | + (target = m or target = m.getAnUltimateImplementor()) + | m = any(SystemIComparableInterface i).getCompareToMethod() or m = any(SystemIComparableTInterface i).getAConstructedGeneric().getAMethod() and m.getSourceDeclaration() = any(SystemIComparableTInterface i).getCompareToMethod() ) - } - or + } or TCompareCall(MethodCall mc) { exists(Method m, Method target | target = mc.getTarget() and - (target = m or target = m.getAnUltimateImplementor()) | + (target = m or target = m.getAnUltimateImplementor()) + | m = any(SystemCollectionsIComparerInterface i).getCompareMethod() or m = any(SystemCollectionsGenericIComparerTInterface i).getAConstructedGeneric().getAMethod() and - m.getSourceDeclaration() = any(SystemCollectionsGenericIComparerTInterface i).getCompareMethod() + m.getSourceDeclaration() = any(SystemCollectionsGenericIComparerTInterface i) + .getCompareMethod() ) - } - or + } or TComparisonOperatorCall(OperatorCall oc, ComparisonKind kind, Expr first, Expr second) { - exists(Operator o | - o = oc.getTarget() | + exists(Operator o | o = oc.getTarget() | o instanceof EQOperator and kind.isEquality() and first = oc.getArgument(0) and @@ -157,15 +152,16 @@ private newtype TComparisonTest = first = oc.getArgument(0) and second = oc.getArgument(1) ) - } - or + } or TCompareWithConstant(ComparisonTest outer, ComparisonKind kind, Expr first, Expr second) { exists(ComparisonKind outerKind, ComparisonTest compare, int i | compare.getComparisonKind().isCompare() and outerKind = outer.getComparisonKind() and outer.getAnArgument() = compare.getExpr() and - i = outer.getAnArgument().getValue().toInt() | - outerKind.isEquality() and ( + i = outer.getAnArgument().getValue().toInt() + | + outerKind.isEquality() and + ( // `x.CompareTo(y) == 0` => `x = y` i = 0 and kind.isEquality() and @@ -185,8 +181,10 @@ private newtype TComparisonTest = second = compare.getSecondArgument() ) or - outerKind.isLessThan() and ( - outer.getFirstArgument() = compare.getExpr() and ( + outerKind.isLessThan() and + ( + outer.getFirstArgument() = compare.getExpr() and + ( // `x.CompareTo(y) < 1` => `x <= y` i = 1 and kind.isLessThanEquals() and @@ -200,7 +198,8 @@ private newtype TComparisonTest = second = compare.getSecondArgument() ) or - outer.getSecondArgument() = compare.getExpr() and ( + outer.getSecondArgument() = compare.getExpr() and + ( // `-1 < x.CompareTo(y)` => `x >= y` i = -1 and kind.isLessThanEquals() and @@ -215,8 +214,10 @@ private newtype TComparisonTest = ) ) or - outerKind.isLessThanEquals() and ( - outer.getFirstArgument() = compare.getExpr() and ( + outerKind.isLessThanEquals() and + ( + outer.getFirstArgument() = compare.getExpr() and + ( // `x.CompareTo(y) <= 0` => `x <= y` i = 0 and kind.isLessThanEquals() and @@ -230,7 +231,8 @@ private newtype TComparisonTest = second = compare.getSecondArgument() ) or - outer.getSecondArgument() = compare.getExpr() and ( + outer.getSecondArgument() = compare.getExpr() and + ( // `0 <= x.CompareTo(y)` => `x >= y` i = 0 and kind.isLessThanEquals() and @@ -262,12 +264,18 @@ class ComparisonTest extends TComparisonTest { /** Gets the comparison kind. */ final ComparisonKind getComparisonKind() { - this = TComparisonOperation(_, result, _, _) or - this = TEqualsCall(_) and result.isEquality() or - this = TCompareToCall(_) and result.isCompare() or - this = TStaticEqualsCall(_) and result.isEquality() or - this = TCompareCall(_) and result.isCompare() or - this = TComparisonOperatorCall(_, result, _, _) or + this = TComparisonOperation(_, result, _, _) + or + this = TEqualsCall(_) and result.isEquality() + or + this = TCompareToCall(_) and result.isCompare() + or + this = TStaticEqualsCall(_) and result.isEquality() + or + this = TCompareCall(_) and result.isCompare() + or + this = TComparisonOperatorCall(_, result, _, _) + or this = TCompareWithConstant(_, result, _, _) } diff --git a/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll b/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll index 226ddfe621d..f45ea4d531a 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/ConsistencyChecks.qll @@ -4,25 +4,26 @@ * Provides functionality for validating that the database and library are in a * consistent state. */ + import csharp private predicate missingLocation(Element e, string m) { ( - e instanceof Declaration - or e instanceof Expr - or e instanceof Stmt - ) - and not e instanceof ImplicitAccessorParameter - and not e instanceof NullType - and not e instanceof Parameter // Bug in Roslyn - params occasionally lack locations - and not e.(Operator).getDeclaringType() instanceof IntType // Roslyn quirk - and not e instanceof Constructor - and not e instanceof ArrayType - and not e instanceof UnknownType - and not e instanceof ArglistType - and not exists(TupleType t | e=t or e=t.getAField()) - and not exists(e.getLocation()) - and m = "Element does not have a location" + e instanceof Declaration or + e instanceof Expr or + e instanceof Stmt + ) and + not e instanceof ImplicitAccessorParameter and + not e instanceof NullType and + not e instanceof Parameter and // Bug in Roslyn - params occasionally lack locations + not e.(Operator).getDeclaringType() instanceof IntType and // Roslyn quirk + not e instanceof Constructor and + not e instanceof ArrayType and + not e instanceof UnknownType and + not e instanceof ArglistType and + not exists(TupleType t | e = t or e = t.getAField()) and + not exists(e.getLocation()) and + m = "Element does not have a location" } private predicate inconsistentGeneric(ConstructedGeneric g, string m) { @@ -40,21 +41,18 @@ module SsaChecks { import Ssa predicate nonUniqueSsaDef(AssignableRead read, string m) { - exists(ControlFlow::Node cfn | - strictcount(Definition def | def.getAReadAtNode(cfn) = read) > 1 - ) - and + exists(ControlFlow::Node cfn | strictcount(Definition def | def.getAReadAtNode(cfn) = read) > 1) and m = "Read is associated with multiple SSA definitions" } predicate notDominatedByDef(AssignableRead read, string m) { exists(Definition def, BasicBlock bb, ControlFlow::Node rnode, ControlFlow::Node dnode, int i | - def.getAReadAtNode(rnode) = read | + def.getAReadAtNode(rnode) = read + | def.definesAt(bb, i) and dnode = bb.getNode(max(int j | j = i or j = 0)) and not dnode.dominates(rnode) - ) - and + ) and m = "Read is not dominated by SSA definition" } @@ -63,14 +61,14 @@ module SsaChecks { // local variables should not have an SSA definition, as that would imply that // the declaration is live (can reach a use without passing through a definition) exists(ExplicitDefinition def | - d = def.getADefinition().(AssignableDefinitions::LocalVariableDefinition).getDeclaration() | + d = def.getADefinition().(AssignableDefinitions::LocalVariableDefinition).getDeclaration() + | not d = any(ForeachStmt fs).getVariableDeclExpr() and not d = any(SpecificCatchClause scc).getVariableDeclExpr() and not d.getVariable().getType() instanceof Struct and not d = any(TypeCase ts).getVariableDeclExpr() and not d = any(IsPatternExpr ipe).getVariableDeclExpr() - ) - and + ) and m = "Local variable declaration has unexpected SSA definition" } @@ -83,8 +81,7 @@ module SsaChecks { module CfgChecks { predicate multipleSuccessors(ControlFlowElement cfe, string m) { - exists(ControlFlow::Node cfn | - cfn = cfe.getAControlFlowNode() | + exists(ControlFlow::Node cfn | cfn = cfe.getAControlFlowNode() | strictcount(cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::NormalSuccessor e))) > 1 and m = "Multiple (non-conditional/exceptional) successors" ) diff --git a/csharp/ql/src/semmle/code/csharp/commons/Constants.qll b/csharp/ql/src/semmle/code/csharp/commons/Constants.qll index 0b56389473f..6a2f2f3cb94 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Constants.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Constants.qll @@ -1,4 +1,5 @@ /** Provides logic for determining constant expressions. */ + import csharp private import semmle.code.csharp.commons.ComparisonTest private import semmle.code.csharp.commons.StructuralComparison as StructuralComparison @@ -7,21 +8,25 @@ private import semmle.code.csharp.commons.StructuralComparison as StructuralComp * Holds if `e` is a condition that always evaluates to Boolean value `b`. */ predicate isConstantCondition(Expr e, boolean b) { - forex(ControlFlow::Node cfn | - cfn = e.getAControlFlowNode() | - exists(cfn.getASuccessorByType(any(ControlFlow::SuccessorTypes::BooleanSuccessor t | t.getValue() = b))) and + forex(ControlFlow::Node cfn | cfn = e.getAControlFlowNode() | + exists( + cfn + .getASuccessorByType(any(ControlFlow::SuccessorTypes::BooleanSuccessor t | + t.getValue() = b + )) + ) and strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1 ) } /** - * Holds if comparison operation `co` is constant with the Boolean value `b`. - * For example, the comparison `x > x` is constantly `false` in - * - * ``` - * int MaxWrong(int x, int y) => x > x ? x : y; - * ``` - */ + * Holds if comparison operation `co` is constant with the Boolean value `b`. + * For example, the comparison `x > x` is constantly `false` in + * + * ``` + * int MaxWrong(int x, int y) => x > x ? x : y; + * ``` + */ predicate isConstantComparison(ComparisonOperation co, boolean b) { co.getValue() = "true" and b = true @@ -38,26 +43,18 @@ predicate isConstantComparison(ComparisonOperation co, boolean b) { private module ConstantComparisonOperation { private import semmle.code.csharp.commons.ComparisonTest - private SimpleType convertedType(Expr expr) { - result = expr.stripImplicitCasts().getType() - } + private SimpleType convertedType(Expr expr) { result = expr.stripImplicitCasts().getType() } private int maxValue(Expr expr) { - if - convertedType(expr) instanceof IntegralType and exists(expr.getValue()) - then - result = expr.getValue().toInt() - else - result = convertedType(expr).maxValue() + if convertedType(expr) instanceof IntegralType and exists(expr.getValue()) + then result = expr.getValue().toInt() + else result = convertedType(expr).maxValue() } private int minValue(Expr expr) { - if - convertedType(expr) instanceof IntegralType and exists(expr.getValue()) - then - result = expr.getValue().toInt() - else - result = convertedType(expr).minValue() + if convertedType(expr) instanceof IntegralType and exists(expr.getValue()) + then result = expr.getValue().toInt() + else result = convertedType(expr).minValue() } /** Holds if the comparison test `cmp` is constant with the value `value`. */ @@ -66,7 +63,7 @@ private module ConstantComparisonOperation { e = cmp.getExpr() and l = cmp.getFirstArgument() and r = cmp.getSecondArgument() - | + | cmp.getComparisonKind().isLessThan() and maxValue(l) < minValue(r) and value = true @@ -85,13 +82,17 @@ private module ConstantComparisonOperation { or // Operands are unequal (maxValue(l) < minValue(r) or maxValue(r) < minValue(l)) and - (cmp.getComparisonKind().isInequality() and value = true or cmp.getComparisonKind().isEquality() and value = false) + ( + cmp.getComparisonKind().isInequality() and value = true + or + cmp.getComparisonKind().isEquality() and value = false + ) or exists(LocalScopeVariable v | l.(VariableRead).getTarget() = v and r.(VariableRead).getTarget() = v and not v.getType() instanceof FloatingPointType // One of the arguments may be NaN - | + | cmp.getComparisonKind().isLessThan() and value = false or cmp.getComparisonKind().isLessThanEquals() and value = true @@ -105,24 +106,19 @@ private module ConstantComparisonOperation { } private class StructuralComparisonConfig extends StructuralComparison::StructuralComparisonConfiguration { - StructuralComparisonConfig() { - this = "CompareIdenticalValues" - } + StructuralComparisonConfig() { this = "CompareIdenticalValues" } override predicate candidate(Element x, Element y) { exists(ComparisonTest ct | - x = ct.getFirstArgument() - and + x = ct.getFirstArgument() and y = ct.getSecondArgument() ) } ComparisonTest getComparisonTest() { exists(Element x, Element y | - result.getFirstArgument() = x - and - result.getSecondArgument() = y - and + result.getFirstArgument() = x and + result.getSecondArgument() = y and same(x, y) ) } @@ -144,20 +140,17 @@ predicate comparesIdenticalValues(ComparisonTest ct) { */ predicate comparesIdenticalValuesNan(ComparisonTest ct, string builtin) { comparesIdenticalValues(ct) and - exists(FloatingPointType fpt, string type, string neg | - fpt = ct.getAnArgument().getType() | + exists(FloatingPointType fpt, string type, string neg | fpt = ct.getAnArgument().getType() | ( fpt instanceof DoubleType and type = "double" or fpt instanceof FloatType and type = "float" - ) - and + ) and ( ct.getComparisonKind().isEquality() and neg = "!" or ct.getComparisonKind().isInequality() and neg = "" - ) - and + ) and builtin = neg + type + ".IsNaN()" ) } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Disposal.qll b/csharp/ql/src/semmle/code/csharp/commons/Disposal.qll index 289999fe03a..a296d1062d1 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Disposal.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Disposal.qll @@ -37,21 +37,24 @@ private predicate disposedCilVariable(CIL::Variable variable) { private predicate disposedCSharpVariable(Variable variable) { // A C# parameter is disposed if its corresponding CIL parameter is disposed exists(CIL::Method m, CIL::Parameter p, int i | - disposedCilVariable(p) and p = m.getRawParameter(i) | + disposedCilVariable(p) and p = m.getRawParameter(i) + | variable = any(Callable c2 | c2.matchesHandle(m)).getRawParameter(i) ) or // Call to a method that disposes it exists(Call call, int arg, VariableRead read | read.getTarget() = variable and - read = call.getArgument(arg) | + read = call.getArgument(arg) + | disposedCSharpVariable(call.getTarget().getParameter(arg)) ) or // Call to `Dispose` exists(MethodCall call, VariableRead read | read.getTarget() = variable and - read = call.getQualifier() | + read = call.getQualifier() + | isDisposeMethod(call.getTarget()) ) or @@ -60,8 +63,8 @@ private predicate disposedCSharpVariable(Variable variable) { or // A variable is disposed if it's assigned to another variable that is disposed exists(AssignableDefinition assign | - assign.getSource() = variable.getAnAccess() - and disposedCSharpVariable(assign.getTarget()) + assign.getSource() = variable.getAnAccess() and + disposedCSharpVariable(assign.getTarget()) ) } diff --git a/csharp/ql/src/semmle/code/csharp/commons/GeneratedCode.qll b/csharp/ql/src/semmle/code/csharp/commons/GeneratedCode.qll index 255522ba20a..65f9899a171 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/GeneratedCode.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/GeneratedCode.qll @@ -6,39 +6,28 @@ private import semmle.code.csharp.frameworks.system.codedom.Compiler /** A source file that contains generated code. */ abstract class GeneratedCodeFile extends SourceFile { } -/** An auto-generated Designer file.*/ +/** An auto-generated Designer file. */ class DesignerFile extends GeneratedCodeFile { - DesignerFile() { - this.getBaseName().toLowerCase().matches("%.designer.cs") - } + DesignerFile() { this.getBaseName().toLowerCase().matches("%.designer.cs") } } /** An auto-generated SpecFlow feature file. */ class FeatureFile extends GeneratedCodeFile { - FeatureFile() { - this.getBaseName().toLowerCase().matches("%.feature.cs") - } + FeatureFile() { this.getBaseName().toLowerCase().matches("%.feature.cs") } } /** An auto-generated XAML code file. */ -class XamlFile extends GeneratedCodeFile { - XamlFile() { - this.getBaseName().matches("%.g.cs") - } -} +class XamlFile extends GeneratedCodeFile { XamlFile() { this.getBaseName().matches("%.g.cs") } } /** An auto-generated XSD code file. */ class AutogenXsdFile extends GeneratedCodeFile { - AutogenXsdFile() { - this.getBaseName().matches("%.autogen.cs") - } + AutogenXsdFile() { this.getBaseName().matches("%.autogen.cs") } } /** An auto-generated CodeDOM file. */ class GeneratedAttributeFile extends GeneratedCodeFile { GeneratedAttributeFile() { - exists(Attribute a | - a.getType() instanceof SystemCodeDomCompilerGeneratedCodeAttributeClass | + exists(Attribute a | a.getType() instanceof SystemCodeDomCompilerGeneratedCodeAttributeClass | a.getFile() = this ) } @@ -46,20 +35,16 @@ class GeneratedAttributeFile extends GeneratedCodeFile { /** A file auto-generated by `sgen.exe`. */ class GeneratedNamespaceFile extends GeneratedCodeFile { - GeneratedNamespaceFile() - { - exists(Namespace n | - n.getATypeDeclaration().getFile() = this | + GeneratedNamespaceFile() { + exists(Namespace n | n.getATypeDeclaration().getFile() = this | n.getQualifiedName() = "Microsoft.Xml.Serialization.GeneratedAssembly" ) } } -/** A file contining comments suggesting it contains generated code.*/ +/** A file contining comments suggesting it contains generated code. */ class GeneratedCommentFile extends GeneratedCodeFile { - GeneratedCommentFile() { - this = any(GeneratedCodeComment c).getLocation().getFile() - } + GeneratedCommentFile() { this = any(GeneratedCodeComment c).getLocation().getFile() } } /** A comment line that indicates generated code. */ @@ -70,12 +55,13 @@ abstract class GeneratedCodeComment extends CommentLine { } */ class GenericGeneratedCodeComment extends GeneratedCodeComment { GenericGeneratedCodeComment() { - exists(string line, string entity, string was, string automatically | - line = getText() | + exists(string line, string entity, string was, string automatically | line = getText() | entity = "file|class|interface|art[ei]fact|module|script" and was = "was|is|has been" and automatically = "automatically |mechanically |auto[- ]?" and - line.regexpMatch("(?i).*\\bThis (" + entity + ") (" + was + ") (" + automatically + ")?generated\\b.*") + line + .regexpMatch("(?i).*\\bThis (" + entity + ") (" + was + ") (" + automatically + + ")?generated\\b.*") ) } } @@ -83,8 +69,7 @@ class GenericGeneratedCodeComment extends GeneratedCodeComment { /** A comment warning against modifications. */ class DontModifyMarkerComment extends GeneratedCodeComment { DontModifyMarkerComment() { - exists(string line | - line = getText() | + exists(string line | line = getText() | line.regexpMatch("(?i).*\\bGenerated by\\b.*\\bDo not edit\\b.*") or line.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*") ) diff --git a/csharp/ql/src/semmle/code/csharp/commons/Loggers.qll b/csharp/ql/src/semmle/code/csharp/commons/Loggers.qll index c3b183ce2c7..fdea8e62d27 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Loggers.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Loggers.qll @@ -1,9 +1,6 @@ /** Provides classes associated with logging frameworks. */ + import csharp /** A logger type that extends from an `ILogger` type. */ -class LoggerType extends RefType { - LoggerType() { - this.getABaseType*().hasName("ILogger") - } -} +class LoggerType extends RefType { LoggerType() { this.getABaseType*().hasName("ILogger") } } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Strings.qll b/csharp/ql/src/semmle/code/csharp/commons/Strings.qll index 908f60e516d..ef97c9da7e3 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Strings.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Strings.qll @@ -7,7 +7,6 @@ private import semmle.code.csharp.frameworks.Format private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.frameworks.system.Text - /** * An expression that appears in a context where an implicit `ToString()` * invocation will take place, unless the expression is already a string. @@ -26,23 +25,23 @@ class ImplicitToStringExpr extends Expr { ImplicitToStringExpr() { exists(Parameter p, Method m | this = getAnAssignedArgumentOrParam(p) and - m = p.getCallable() | + m = p.getCallable() + | m = any(SystemTextStringBuilderClass c).getAMethod() and m.getName().regexpMatch("Append(Line)?") or p instanceof StringFormatItemParameter and not p.getType() = any(ArrayType at | - at.getElementType() instanceof ObjectType and - this.getType().isImplicitlyConvertibleTo(at) - ) + at.getElementType() instanceof ObjectType and + this.getType().isImplicitlyConvertibleTo(at) + ) or m = any(SystemClass c | c.hasName("Console")).getAMethod() and m.getName().regexpMatch("Write(Line)?") and p.getPosition() = 0 ) or - exists(AddExpr add, Expr o | - o = add.getAnOperand() | + exists(AddExpr add, Expr o | o = add.getAnOperand() | o.stripImplicitCasts().getType() instanceof StringType and this = add.getOtherOperand(o) ) @@ -55,8 +54,7 @@ private Expr getAnAssignedArgumentOrParam(Parameter p) { result = p.getAnAssignedArgument() or p.isParams() and - exists(MethodCall mc, int i | - mc.getTarget().getAParameter() = p | + exists(MethodCall mc, int i | mc.getTarget().getAParameter() = p | result = mc.getArgument(i) and i >= p.getPosition() ) diff --git a/csharp/ql/src/semmle/code/csharp/commons/StructuralComparison.qll b/csharp/ql/src/semmle/code/csharp/commons/StructuralComparison.qll index 36221527741..648e78c633a 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/StructuralComparison.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/StructuralComparison.qll @@ -2,6 +2,7 @@ * Provides functionality for performing structural comparison of * expressions and statements. */ + import csharp /** Gets the declaration referenced by the expression `e`, if any. */ @@ -21,10 +22,9 @@ private int elementKind(Element e) { } private int getNumberOfActualChildren(Element e) { - if e.(MemberAccess).targetIsThisInstance() then - result = e.getNumberOfChildren() - 1 - else - result = e.getNumberOfChildren() + if e.(MemberAccess).targetIsThisInstance() + then result = e.getNumberOfChildren() - 1 + else result = e.getNumberOfChildren() } /** @@ -61,68 +61,53 @@ abstract class StructuralComparisonConfiguration extends string { ( candidate(x, y) or - exists(Element xParent, Element yParent, int i | - candidateInternal(xParent, yParent) | - hasChild(xParent, i, x) - and + exists(Element xParent, Element yParent, int i | candidateInternal(xParent, yParent) | + hasChild(xParent, i, x) and hasChild(yParent, i, y) ) ) } - pragma [noinline] - private predicate hasChild(Element e, int i, Element child) { - child = e.getChild(i) - } + pragma[noinline] + private predicate hasChild(Element e, int i, Element child) { child = e.getChild(i) } - private predicate sameByValue(Expr x, Expr y) { - sameByValueAux(x, y, y.getValue()) - } + private predicate sameByValue(Expr x, Expr y) { sameByValueAux(x, y, y.getValue()) } - pragma [noinline] + pragma[noinline] private predicate sameByValueAux(Expr x, Expr y, string value) { candidateInternal(x, y) and value = x.getValue() } - pragma [nomagic] + pragma[nomagic] private predicate sameByStructure(Element x, Element y) { // At least one of `x` and `y` must not have a value, they must have // the same kind, and the same number of children - sameByStructureCandidate(x, y, elementKind(y), getNumberOfActualChildren(y)) - and + sameByStructureCandidate(x, y, elementKind(y), getNumberOfActualChildren(y)) and // If one of them has a reference attribute, they should both reference // the same node - (exists(referenceAttribute(x)) implies - referenceAttribute(x) = referenceAttribute(y)) - and + (exists(referenceAttribute(x)) implies referenceAttribute(x) = referenceAttribute(y)) and // x is a member access on `this` iff y is - (x.(MemberAccess).targetIsThisInstance() implies - y.(MemberAccess).targetIsThisInstance()) - and - (y.(MemberAccess).targetIsThisInstance() implies - x.(MemberAccess).targetIsThisInstance()) - and + (x.(MemberAccess).targetIsThisInstance() implies y.(MemberAccess).targetIsThisInstance()) and + (y.(MemberAccess).targetIsThisInstance() implies x.(MemberAccess).targetIsThisInstance()) and // All of their corresponding children must be structurally equal forall(int i, Element xc | xc = x.getChild(i) and // exclude `this` qualifier, which has been checked above - not (i = -1 and x.(MemberAccess).targetIsThisInstance()) | + not (i = -1 and x.(MemberAccess).targetIsThisInstance()) + | sameInternal(xc, y.getChild(i)) ) } private predicate sameByStructureCandidate(Element x, Element y, int elementKind, int children) { - candidateInternal(x, y) - and - elementKind = elementKind(x) - and - children = getNumberOfActualChildren(x) - and + candidateInternal(x, y) and + elementKind = elementKind(x) and + children = getNumberOfActualChildren(x) and not (x.(Expr).hasValue() and y.(Expr).hasValue()) } - pragma [nomagic] + pragma[nomagic] private predicate sameInternal(Element x, Element y) { sameByValue(x, y) or @@ -135,8 +120,7 @@ abstract class StructuralComparisonConfiguration extends string { * `candidate(x, y)` must hold. */ predicate same(Element x, Element y) { - candidate(x, y) - and + candidate(x, y) and sameInternal(x, y) } } @@ -188,68 +172,53 @@ module Internal { ( candidate(x, y) or - exists(Element xParent, Element yParent, int i | - candidateInternal(xParent, yParent) | - hasChild(xParent, i, x) - and + exists(Element xParent, Element yParent, int i | candidateInternal(xParent, yParent) | + hasChild(xParent, i, x) and hasChild(yParent, i, y) ) ) } - pragma [noinline] - private predicate hasChild(Element e, int i, Element child) { - child = e.getChild(i) - } + pragma[noinline] + private predicate hasChild(Element e, int i, Element child) { child = e.getChild(i) } - private predicate sameByValue(Expr x, Expr y) { - sameByValueAux(x, y, y.getValue()) - } + private predicate sameByValue(Expr x, Expr y) { sameByValueAux(x, y, y.getValue()) } - pragma [noinline] + pragma[noinline] private predicate sameByValueAux(Expr x, Expr y, string value) { candidateInternal(x, y) and value = x.getValue() } - pragma [nomagic] + pragma[nomagic] private predicate sameByStructure(Element x, Element y) { // At least one of `x` and `y` must not have a value, they must have // the same kind, and the same number of children - sameByStructureCandidate(x, y, elementKind(y), getNumberOfActualChildren(y)) - and + sameByStructureCandidate(x, y, elementKind(y), getNumberOfActualChildren(y)) and // If one of them has a reference attribute, they should both reference // the same node - (exists(referenceAttribute(x)) implies - referenceAttribute(x) = referenceAttribute(y)) - and + (exists(referenceAttribute(x)) implies referenceAttribute(x) = referenceAttribute(y)) and // x is a member access on `this` iff y is - (x.(MemberAccess).targetIsThisInstance() implies - y.(MemberAccess).targetIsThisInstance()) - and - (y.(MemberAccess).targetIsThisInstance() implies - x.(MemberAccess).targetIsThisInstance()) - and + (x.(MemberAccess).targetIsThisInstance() implies y.(MemberAccess).targetIsThisInstance()) and + (y.(MemberAccess).targetIsThisInstance() implies x.(MemberAccess).targetIsThisInstance()) and // All of their corresponding children must be structurally equal forall(int i, Element xc | xc = x.getChild(i) and // exclude `this` qualifier, which has been checked above - not (i = -1 and x.(MemberAccess).targetIsThisInstance()) | + not (i = -1 and x.(MemberAccess).targetIsThisInstance()) + | sameInternal(xc, y.getChild(i)) ) } private predicate sameByStructureCandidate(Element x, Element y, int elementKind, int children) { - candidateInternal(x, y) - and - elementKind = elementKind(x) - and - children = getNumberOfActualChildren(x) - and + candidateInternal(x, y) and + elementKind = elementKind(x) and + children = getNumberOfActualChildren(x) and not (x.(Expr).hasValue() and y.(Expr).hasValue()) } - pragma [nomagic] + pragma[nomagic] private predicate sameInternal(Element x, Element y) { sameByValue(x, y) or @@ -262,8 +231,7 @@ module Internal { * `candidate(x, y)` must hold. */ predicate same(Element x, Element y) { - candidate(x, y) - and + candidate(x, y) and sameInternal(x, y) } } diff --git a/csharp/ql/src/semmle/code/csharp/commons/TargetFramework.qll b/csharp/ql/src/semmle/code/csharp/commons/TargetFramework.qll index 530959ff5c8..c6532eebcb3 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/TargetFramework.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/TargetFramework.qll @@ -25,9 +25,7 @@ class TargetFrameworkAttribute extends Attribute { * ``` * is `".NETFramework,Version=v4.6.1"`. */ - string getFrameworkName() { - result = this.getArgument(0).getValue() - } + string getFrameworkName() { result = this.getArgument(0).getValue() } private string frameworkCapture(int n) { result = this.getFrameworkName().regexpCapture("([^,]+),Version=v(.+)", n) @@ -40,9 +38,7 @@ class TargetFrameworkAttribute extends Attribute { * ``` * is `".NETFramework"`. Other framework types include `".NETStandard"` and `".NETCoreApp"`. */ - string getFrameworkType() { - result = this.frameworkCapture(1) - } + string getFrameworkType() { result = this.frameworkCapture(1) } /** * Gets the framework version of this attribute. For example, the framework version of @@ -52,29 +48,20 @@ class TargetFrameworkAttribute extends Attribute { * is `"4.6.1"`. Note that you can use the `Version` class to compare versions, for example * `target.getFrameworkVersion().isEarlierThan("4.6")`. */ - Version getFrameworkVersion() { - result = this.frameworkCapture(2) - } + Version getFrameworkVersion() { result = this.frameworkCapture(2) } /** Holds if the framework type is .NET Desktop. */ - predicate isNetFramework() { - this.getFrameworkType() = ".NETFramework" - } + predicate isNetFramework() { this.getFrameworkType() = ".NETFramework" } /** Holds if the framework type is .NET Standard. */ - predicate isNetStandard() { - this.getFrameworkType() = ".NETStandard" } + predicate isNetStandard() { this.getFrameworkType() = ".NETStandard" } /** Holds if the framework type is .NET Core. */ - predicate isNetCore() { - this.getFrameworkType() = ".NETCoreApp" - } + predicate isNetCore() { this.getFrameworkType() = ".NETCoreApp" } /** * Holds if element `e` specifies this target version, because it is * compiled in the assembly of this attribute. */ - predicate hasElement(Element e) { - assembly = e.getALocation() - } + predicate hasElement(Element e) { assembly = e.getALocation() } } diff --git a/csharp/ql/src/semmle/code/csharp/commons/Util.qll b/csharp/ql/src/semmle/code/csharp/commons/Util.qll index 3027da89b41..203d84cbef6 100644 --- a/csharp/ql/src/semmle/code/csharp/commons/Util.qll +++ b/csharp/ql/src/semmle/code/csharp/commons/Util.qll @@ -8,9 +8,8 @@ class MainMethod extends Method { this.hasName("Main") and this.isStatic() and (this.getReturnType() instanceof VoidType or this.getReturnType() instanceof IntType) and - if this.getNumberOfParameters() = 1 then - this.getParameter(0).getType().(ArrayType).getElementType() instanceof StringType - else - this.getNumberOfParameters() = 0 + if this.getNumberOfParameters() = 1 + then this.getParameter(0).getType().(ArrayType).getElementType() instanceof StringType + else this.getNumberOfParameters() = 0 } } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll index 7ab1a0ba3b3..5e2dd11d466 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/BasicBlocks.qll @@ -11,9 +11,7 @@ private import ControlFlow::SuccessorTypes */ class BasicBlock extends TBasicBlockStart { /** Gets an immediate successor of this basic block, if any. */ - BasicBlock getASuccessor() { - result.getFirstNode() = getLastNode().getASuccessor() - } + BasicBlock getASuccessor() { result.getFirstNode() = getLastNode().getASuccessor() } /** Gets an immediate successor of this basic block of a given type, if any. */ BasicBlock getASuccessorByType(ControlFlow::SuccessorType t) { @@ -21,9 +19,7 @@ class BasicBlock extends TBasicBlockStart { } /** Gets an immediate predecessor of this basic block, if any. */ - BasicBlock getAPredecessor() { - result.getASuccessor() = this - } + BasicBlock getAPredecessor() { result.getASuccessor() = this } /** Gets an immediate predecessor of this basic block of a given type, if any. */ BasicBlock getAPredecessorByType(ControlFlow::SuccessorType t) { @@ -46,9 +42,7 @@ class BasicBlock extends TBasicBlockStart { * The basic block on line 2 is an immediate `true` successor of the * basic block on line 1. */ - BasicBlock getATrueSuccessor() { - result.getFirstNode() = getLastNode().getATrueSuccessor() - } + BasicBlock getATrueSuccessor() { result.getFirstNode() = getLastNode().getATrueSuccessor() } /** * Gets an immediate `false` successor, if any. @@ -66,9 +60,7 @@ class BasicBlock extends TBasicBlockStart { * The basic block on line 2 is an immediate `false` successor of the * basic block on line 1. */ - BasicBlock getAFalseSuccessor() { - result.getFirstNode() = getLastNode().getAFalseSuccessor() - } + BasicBlock getAFalseSuccessor() { result.getFirstNode() = getLastNode().getAFalseSuccessor() } /** * Gets an immediate `null` successor, if any. @@ -86,8 +78,7 @@ class BasicBlock extends TBasicBlockStart { * The node on line 2 is an immediate `null` successor of the node * `x` on line 1. */ - deprecated - BasicBlock getANullSuccessor() { + deprecated BasicBlock getANullSuccessor() { result.getFirstNode() = getLastNode().getANullSuccessor() } @@ -106,8 +97,7 @@ class BasicBlock extends TBasicBlockStart { * The node `x?.M()`, representing the call to `M`, is a non-`null` successor * of the node `x`. */ - deprecated - BasicBlock getANonNullSuccessor() { + deprecated BasicBlock getANonNullSuccessor() { result.getFirstNode() = getLastNode().getANonNullSuccessor() } @@ -115,29 +105,19 @@ class BasicBlock extends TBasicBlockStart { ControlFlow::Node getNode(int pos) { bbIndex(getFirstNode(), result, pos) } /** Gets a control flow node in this basic block. */ - ControlFlow::Node getANode() { - result = getNode(_) - } + ControlFlow::Node getANode() { result = getNode(_) } /** Gets the first control flow node in this basic block. */ - ControlFlow::Node getFirstNode() { - this = TBasicBlockStart(result) - } + ControlFlow::Node getFirstNode() { this = TBasicBlockStart(result) } /** Gets the last control flow node in this basic block. */ - ControlFlow::Node getLastNode() { - result = getNode(length() - 1) - } + ControlFlow::Node getLastNode() { result = getNode(length() - 1) } /** Gets the callable that this basic block belongs to. */ - Callable getCallable() { - result = this.getAPredecessor().getCallable() - } + Callable getCallable() { result = this.getAPredecessor().getCallable() } /** Gets the length of this basic block. */ - int length() { - result = strictcount(getANode()) - } + int length() { result = strictcount(getANode()) } /** * Holds if this basic block immediately dominates basic block `bb`. @@ -160,9 +140,7 @@ class BasicBlock extends TBasicBlockStart { * basic block on line 4 (all paths from the entry point of `M` * to `return s.Length;` must go through the null check). */ - predicate immediatelyDominates(BasicBlock bb) { - bbIDominates(this, bb) - } + predicate immediatelyDominates(BasicBlock bb) { bbIDominates(this, bb) } /** * Holds if this basic block strictly dominates basic block `bb`. @@ -185,9 +163,7 @@ class BasicBlock extends TBasicBlockStart { * basic block on line 4 (all paths from the entry point of `M` * to `return s.Length;` must go through the null check). */ - predicate strictlyDominates(BasicBlock bb) { - bbIDominates+(this, bb) - } + predicate strictlyDominates(BasicBlock bb) { bbIDominates+(this, bb) } /** * Holds if this basic block dominates basic block `bb`. @@ -247,10 +223,7 @@ class BasicBlock extends TBasicBlockStart { /** * Holds if this basic block dominates a predecessor of `df`. */ - private - predicate dominatesPredecessor(BasicBlock df) { - dominates(df.getAPredecessor()) - } + private predicate dominatesPredecessor(BasicBlock df) { dominates(df.getAPredecessor()) } /** * Gets the basic block that immediately dominates this basic block, if any. @@ -274,9 +247,7 @@ class BasicBlock extends TBasicBlockStart { * to `return s.Length;` must go through the null check, and the null check * is an immediate predecessor of `return s.Length;`). */ - BasicBlock getImmediateDominator() { - bbIDominates(result, this) - } + BasicBlock getImmediateDominator() { bbIDominates(result, this) } /** * Holds if this basic block strictly post-dominates basic block `bb`. @@ -302,9 +273,7 @@ class BasicBlock extends TBasicBlockStart { * line 3 (all paths to the exit point of `M` from `return s.Length;` * must go through the `WriteLine` call). */ - predicate strictlyPostDominates(BasicBlock bb) { - bbIPostDominates+(this, bb) - } + predicate strictlyPostDominates(BasicBlock bb) { bbIPostDominates+(this, bb) } /** * Holds if this basic block post-dominates basic block `bb`. @@ -343,28 +312,23 @@ class BasicBlock extends TBasicBlockStart { * even if this basic block is syntactically inside a `while` loop if the * necessary back edges are unreachable. */ - predicate inLoop() { - this.getASuccessor+() = this - } + predicate inLoop() { this.getASuccessor+() = this } /** Gets a textual representation of this basic block. */ - string toString() { - result = getFirstNode().toString() - } + string toString() { result = getFirstNode().toString() } /** Gets the location of this basic block. */ - Location getLocation() { - result = getFirstNode().getLocation() - } + Location getLocation() { result = getFirstNode().getLocation() } } /** * Internal implementation details. */ -private cached module Internal { +cached +private module Internal { /** Internal representation of basic blocks. */ - cached newtype TBasicBlock = - TBasicBlockStart(ControlFlow::Node cfn) { startsBB(cfn) } + cached + newtype TBasicBlock = TBasicBlockStart(ControlFlow::Node cfn) { startsBB(cfn) } /** Holds if `cfn` starts a new basic block. */ private predicate startsBB(ControlFlow::Node cfn) { @@ -372,7 +336,9 @@ private cached module Internal { or cfn.isJoin() or - exists(ControlFlow::Node pred | pred = cfn.getAPredecessor() | strictcount(pred.getASuccessor()) > 1) + exists(ControlFlow::Node pred | pred = cfn.getAPredecessor() | + strictcount(pred.getASuccessor()) > 1 + ) } /** @@ -398,9 +364,7 @@ private cached module Internal { * Holds if the first node of basic block `succ` is a control flow * successor of the last node of basic block `pred`. */ - private predicate succBB(BasicBlock pred, BasicBlock succ) { - succ = pred.getASuccessor() - } + private predicate succBB(BasicBlock pred, BasicBlock succ) { succ = pred.getASuccessor() } /** Holds if `dom` is an immediate dominator of `bb`. */ cached @@ -408,9 +372,7 @@ private cached module Internal { idominance(entryBB/1, succBB/2)(_, dom, bb) /** Holds if `pred` is a basic block predecessor of `succ`. */ - private predicate predBB(BasicBlock succ, BasicBlock pred) { - succBB(pred, succ) - } + private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) } /** Holds if `dom` is an immediate post-dominator of `bb`. */ cached @@ -426,9 +388,7 @@ private import Internal class EntryBasicBlock extends BasicBlock { EntryBasicBlock() { entryBB(this) } - override Callable getCallable() { - result.getEntryPoint() = this.getFirstNode() - } + override Callable getCallable() { result.getEntryPoint() = this.getFirstNode() } } /** Holds if `bb` is an entry basic block. */ @@ -440,32 +400,22 @@ private predicate entryBB(BasicBlock bb) { * An exit basic block, that is, a basic block whose last node is * the exit node of a callable. */ -class ExitBasicBlock extends BasicBlock { - ExitBasicBlock() { exitBB(this) } -} +class ExitBasicBlock extends BasicBlock { ExitBasicBlock() { exitBB(this) } } /** Holds if `bb` is an exit basic block. */ -private predicate exitBB(BasicBlock bb) { - bb.getLastNode() instanceof ControlFlow::Nodes::ExitNode -} +private predicate exitBB(BasicBlock bb) { bb.getLastNode() instanceof ControlFlow::Nodes::ExitNode } /** A basic block with more than one predecessor. */ -class JoinBlock extends BasicBlock { - JoinBlock() { getFirstNode().isJoin() } -} +class JoinBlock extends BasicBlock { JoinBlock() { getFirstNode().isJoin() } } /** A basic block that is an immediate predecessor of a join block. */ class JoinBlockPredecessor extends BasicBlock { - JoinBlockPredecessor() { - this.getASuccessor() instanceof JoinBlock - } + JoinBlockPredecessor() { this.getASuccessor() instanceof JoinBlock } } /** A basic block that terminates in a condition, splitting the subsequent control flow. */ class ConditionBlock extends BasicBlock { - ConditionBlock() { - this.getLastNode().isCondition() - } + ConditionBlock() { this.getLastNode().isCondition() } /** * Holds if basic block `succ` is immediately controlled by this basic @@ -476,10 +426,7 @@ class ConditionBlock extends BasicBlock { pragma[nomagic] predicate immediatelyControls(BasicBlock succ, ConditionalSuccessor s) { succ = this.getASuccessorByType(s) and - forall(BasicBlock pred | - pred = succ.getAPredecessor() and pred != this | - succ.dominates(pred) - ) + forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this | succ.dominates(pred)) } /** @@ -521,10 +468,8 @@ class ConditionBlock extends BasicBlock { * that `this` strictly dominates `controlled` so that isn't necessary to check * directly. */ - exists(BasicBlock succ | - this.immediatelyControls(succ, s) | - succ.dominates(controlled) - ) + + exists(BasicBlock succ | this.immediatelyControls(succ, s) | succ.dominates(controlled)) } /** @@ -533,8 +478,7 @@ class ConditionBlock extends BasicBlock { * the callable entry point by going via the `null` edge (`isNull = true`) * or non-`null` edge (`isNull = false`) out of this basic block. */ - deprecated - predicate controlsNullness(BasicBlock controlled, boolean isNull) { + deprecated predicate controlsNullness(BasicBlock controlled, boolean isNull) { this.controls(controlled, any(NullnessSuccessor s | s.getValue() = isNull)) } @@ -573,8 +517,9 @@ class ConditionBlock extends BasicBlock { // // In the former case, `x` and `y` control `A`, in the latter case // only `x & y` controls `A` if we do not take sub conditions into account. - deprecated - predicate controlsSubCond(BasicBlock controlled, boolean testIsTrue, Expr cond, boolean condIsTrue) { + deprecated predicate controlsSubCond( + BasicBlock controlled, boolean testIsTrue, Expr cond, boolean condIsTrue + ) { impliesSub(getLastNode().getElement(), cond, testIsTrue, condIsTrue) and controls(controlled, any(BooleanSuccessor s | s.getValue() = testIsTrue)) } @@ -584,22 +529,23 @@ class ConditionBlock extends BasicBlock { * Holds if `e2` is a sub expression of (Boolean) expression `e1`, and * if `e1` has value `b1` then `e2` must have value `b2`. */ -deprecated -private predicate impliesSub(Expr e1, Expr e2, boolean b1, boolean b2) { - if e1 instanceof LogicalNotExpr then ( - impliesSub(e1.(LogicalNotExpr).getOperand(), e2, b1.booleanNot(), b2) - ) - else if e1 instanceof BitwiseAndExpr or e1 instanceof LogicalAndExpr then ( - impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and - b1 = true - ) - else if e1 instanceof BitwiseOrExpr or e1 instanceof LogicalOrExpr then ( - impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and - b1 = false - ) else ( - e1.getType() instanceof BoolType and - e1 = e2 and - b1 = b2 and - (b1 = true or b1 = false) - ) +deprecated private predicate impliesSub(Expr e1, Expr e2, boolean b1, boolean b2) { + if e1 instanceof LogicalNotExpr + then impliesSub(e1.(LogicalNotExpr).getOperand(), e2, b1.booleanNot(), b2) + else + if e1 instanceof BitwiseAndExpr or e1 instanceof LogicalAndExpr + then + impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and + b1 = true + else + if e1 instanceof BitwiseOrExpr or e1 instanceof LogicalOrExpr + then ( + impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and + b1 = false + ) else ( + e1.getType() instanceof BoolType and + e1 = e2 and + b1 = b2 and + (b1 = true or b1 = false) + ) } diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/Completion.qll b/csharp/ql/src/semmle/code/csharp/controlflow/Completion.qll index d6f1ca16d86..ce41d25aeb5 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/Completion.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/Completion.qll @@ -25,41 +25,22 @@ private import semmle.code.csharp.frameworks.System // Internal representation of completions private newtype TCompletion = - TNormalCompletion() - or + TNormalCompletion() or TBooleanCompletion(boolean outerValue, boolean innerValue) { (outerValue = true or outerValue = false) and (innerValue = true or innerValue = false) - } - or - TNullnessCompletion(boolean isNull) { - isNull = true or isNull = false - } - or - TMatchingCompletion(boolean isMatch) { - isMatch = true or isMatch = false - } - or - TEmptinessCompletion(boolean isEmpty) { - isEmpty = true or isEmpty = false - } - or - TReturnCompletion() - or - TBreakCompletion() - or - TBreakNormalCompletion() - or - TContinueCompletion() - or - TGotoLabelCompletion(GotoLabelStmt goto) - or - TGotoCaseCompletion(GotoCaseStmt goto) - or - TGotoDefaultCompletion() - or - TThrowCompletion(ExceptionClass ec) - or + } or + TNullnessCompletion(boolean isNull) { isNull = true or isNull = false } or + TMatchingCompletion(boolean isMatch) { isMatch = true or isMatch = false } or + TEmptinessCompletion(boolean isEmpty) { isEmpty = true or isEmpty = false } or + TReturnCompletion() or + TBreakCompletion() or + TBreakNormalCompletion() or + TContinueCompletion() or + TGotoLabelCompletion(GotoLabelStmt goto) or + TGotoCaseCompletion(GotoCaseStmt goto) or + TGotoDefaultCompletion() or + TThrowCompletion(ExceptionClass ec) or TExitCompletion() /** @@ -81,9 +62,9 @@ class Completion extends TCompletion { predicate isValidFor(ControlFlowElement cfe) { this.(ThrowCompletion).getExceptionClass() = cfe.(TriedControlFlowElement).getAThrownException() or - if mustHaveBooleanCompletion(cfe) then - exists(boolean value | - isBooleanConstant(cfe, value) | + if mustHaveBooleanCompletion(cfe) + then + exists(boolean value | isBooleanConstant(cfe, value) | this = TBooleanCompletion(value, value) ) or @@ -95,26 +76,24 @@ class Completion extends TCompletion { // non-`null` completion) mustHaveNullnessCompletion(cfe) and this = TNullnessCompletion(true) - else if mustHaveNullnessCompletion(cfe) then - exists(boolean value | - isNullnessConstant(cfe, value) | - this = TNullnessCompletion(value) - ) - or - not isNullnessConstant(cfe, _) and - this = TNullnessCompletion(_) - else if mustHaveMatchingCompletion(cfe) then - exists(boolean value | - isMatchingConstant(cfe, value) | - this = TMatchingCompletion(value) - ) - or - not isMatchingConstant(cfe, _) and - this = TMatchingCompletion(_) - else if mustHaveEmptinessCompletion(cfe) then - this = TEmptinessCompletion(_) else - this = TNormalCompletion() + if mustHaveNullnessCompletion(cfe) + then + exists(boolean value | isNullnessConstant(cfe, value) | this = TNullnessCompletion(value)) + or + not isNullnessConstant(cfe, _) and + this = TNullnessCompletion(_) + else + if mustHaveMatchingCompletion(cfe) + then + exists(boolean value | isMatchingConstant(cfe, value) | this = TMatchingCompletion(value)) + or + not isMatchingConstant(cfe, _) and + this = TMatchingCompletion(_) + else + if mustHaveEmptinessCompletion(cfe) + then this = TEmptinessCompletion(_) + else this = TNormalCompletion() } /** @@ -147,14 +126,13 @@ private predicate isBooleanConstant(Expr e, boolean value) { */ private predicate isNullnessConstant(Expr e, boolean value) { mustHaveNullnessCompletion(e) and - exists(Expr stripped | - stripped = e.stripCasts() | + exists(Expr stripped | stripped = e.stripCasts() | stripped.getType() = any(ValueType t | - not t instanceof NullableType and - // Extractor bug: the type of `x?.Length` is reported as `int`, but it should - // be `int?` - not getQualifier*(stripped).(QualifiableExpr).isConditional() - ) and + not t instanceof NullableType and + // Extractor bug: the type of `x?.Length` is reported as `int`, but it should + // be `int?` + not getQualifier*(stripped).(QualifiableExpr).isConditional() + ) and value = false or stripped instanceof NullLiteral and @@ -176,22 +154,17 @@ private Expr getQualifier(QualifiableExpr e) { * non-matches (`value = false`). */ private predicate isMatchingConstant(Expr e, boolean value) { - exists(SwitchStmt ss | - mustHaveMatchingCompletion(ss, e) | - exists(Expr stripped | - stripped = ss.getCondition().stripCasts() | + exists(SwitchStmt ss | mustHaveMatchingCompletion(ss, e) | + exists(Expr stripped | stripped = ss.getCondition().stripCasts() | exists(ConstCase cc, string strippedValue | cc = ss.getAConstCase() and e = cc.getExpr() and - strippedValue = stripped.getValue() | - if strippedValue = e.getValue() then - value = true - else - value = false + strippedValue = stripped.getValue() + | + if strippedValue = e.getValue() then value = true else value = false ) or - exists(TypeCase tc, Type t, Type strippedType | - tc = ss.getATypeCase() | + exists(TypeCase tc, Type t, Type strippedType | tc = ss.getATypeCase() | e = tc.getTypeAccess() and t = e.getType() and strippedType = stripped.getType() and @@ -207,36 +180,34 @@ private predicate isMatchingConstant(Expr e, boolean value) { /** A control flow element that is inside a `try` block. */ private class TriedControlFlowElement extends ControlFlowElement { - TriedControlFlowElement() { - this = any(TryStmt try).getATriedElement() - } + TriedControlFlowElement() { this = any(TryStmt try).getATriedElement() } /** * Gets an exception class that is potentially thrown by this element, if any. */ ExceptionClass getAThrownException() { this = any(UnaryOperation uo | - not uo instanceof UnaryBitwiseOperation and - uo.getType() instanceof IntegralType and - result instanceof SystemOverflowExceptionClass - ) + not uo instanceof UnaryBitwiseOperation and + uo.getType() instanceof IntegralType and + result instanceof SystemOverflowExceptionClass + ) or this = any(CastExpr ce | - ce.getType() instanceof IntegralType and - result instanceof SystemOverflowExceptionClass - or - invalidCastCandidate(ce) and - result instanceof SystemInvalidCastExceptionClass - ) + ce.getType() instanceof IntegralType and + result instanceof SystemOverflowExceptionClass + or + invalidCastCandidate(ce) and + result instanceof SystemInvalidCastExceptionClass + ) or this instanceof Call and result instanceof SystemExceptionClass or this = any(MemberAccess ma | - not ma.isConditional() and - ma.hasQualifier() and - result instanceof SystemNullReferenceExceptionClass - ) + not ma.isConditional() and + ma.hasQualifier() and + result instanceof SystemNullReferenceExceptionClass + ) or this instanceof DelegateCreation and result instanceof SystemOutOfMemoryExceptionClass @@ -245,27 +216,27 @@ private class TriedControlFlowElement extends ControlFlowElement { result instanceof SystemOutOfMemoryExceptionClass or this = any(AddExpr ae | - ae.getType() instanceof StringType and - result instanceof SystemOutOfMemoryExceptionClass - or - ae.getType() instanceof IntegralType and - result instanceof SystemOverflowExceptionClass - ) + ae.getType() instanceof StringType and + result instanceof SystemOutOfMemoryExceptionClass + or + ae.getType() instanceof IntegralType and + result instanceof SystemOverflowExceptionClass + ) or this = any(SubExpr se | - se.getType() instanceof IntegralType and - result instanceof SystemOverflowExceptionClass - ) + se.getType() instanceof IntegralType and + result instanceof SystemOverflowExceptionClass + ) or this = any(MulExpr me | - me.getType() instanceof IntegralType and - result instanceof SystemOverflowExceptionClass - ) + me.getType() instanceof IntegralType and + result instanceof SystemOverflowExceptionClass + ) or this = any(DivExpr de | - not de.getDenominator().getValue().toInt() != 0 and - result instanceof SystemDivideByZeroExceptionClass - ) + not de.getDenominator().getValue().toInt() != 0 and + result instanceof SystemDivideByZeroExceptionClass + ) or this instanceof RemExpr and result instanceof SystemDivideByZeroExceptionClass @@ -278,7 +249,7 @@ private class TriedControlFlowElement extends ControlFlowElement { } } -pragma [noinline] +pragma[noinline] private predicate invalidCastCandidate(CastExpr ce) { ce.getType() = ce.getExpr().getType().(ValueOrRefType).getASubType+() } @@ -301,28 +272,15 @@ private predicate mustHaveBooleanCompletion(Expr e) { * `B` is the Boolean completion of `A && B`. */ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent) { - exists(IfStmt is | - is.getCondition() = e | - isBooleanCompletionForParent = false - ) + exists(IfStmt is | is.getCondition() = e | isBooleanCompletionForParent = false) or - exists(LoopStmt ls | - ls.getCondition() = e | - isBooleanCompletionForParent = false - ) + exists(LoopStmt ls | ls.getCondition() = e | isBooleanCompletionForParent = false) or - exists(CaseStmt cs | - cs.getCondition() = e | - isBooleanCompletionForParent = false - ) + exists(CaseStmt cs | cs.getCondition() = e | isBooleanCompletionForParent = false) or - exists(SpecificCatchClause scc | - scc.getFilterClause() = e | - isBooleanCompletionForParent = false - ) + exists(SpecificCatchClause scc | scc.getFilterClause() = e | isBooleanCompletionForParent = false) or - exists(LogicalNotExpr lne | - lne.getAnOperand() = e | + exists(LogicalNotExpr lne | lne.getAnOperand() = e | inBooleanContext(lne, _) and isBooleanCompletionForParent = true ) @@ -354,8 +312,7 @@ private predicate inBooleanContext(Expr e, boolean isBooleanCompletionForParent) isBooleanCompletionForParent = true ) or - exists(NullCoalescingExpr nce | - nce.getAnOperand() = e | + exists(NullCoalescingExpr nce | nce.getAnOperand() = e | inBooleanContext(nce, _) and isBooleanCompletionForParent = true ) @@ -379,25 +336,19 @@ private predicate mustHaveNullnessCompletion(Expr e) { * is the nullness completion of `A ?? B`. */ private predicate inNullnessContext(Expr e, boolean isNullnessCompletionForParent) { - exists(NullCoalescingExpr nce | - e = nce.getLeftOperand() | - isNullnessCompletionForParent = false - ) + exists(NullCoalescingExpr nce | e = nce.getLeftOperand() | isNullnessCompletionForParent = false) or - exists(QualifiableExpr qe | - qe.isConditional() | + exists(QualifiableExpr qe | qe.isConditional() | e = qe.getChildExpr(-1) and isNullnessCompletionForParent = false ) or - exists(ConditionalExpr ce | - inNullnessContext(ce, _) | + exists(ConditionalExpr ce | inNullnessContext(ce, _) | (e = ce.getThen() or e = ce.getElse()) and isNullnessCompletionForParent = true ) or - exists(NullCoalescingExpr nce | - inNullnessContext(nce, _) | + exists(NullCoalescingExpr nce | inNullnessContext(nce, _) | e = nce.getRightOperand() and isNullnessCompletionForParent = true ) @@ -442,9 +393,7 @@ predicate foreachEmptiness(ForeachStmt fs, ControlFlowElement cfe) { * Holds if a normal completion of `cfe` must be an emptiness completion. Thats is, * whether `cfe` determines whether to execute the body of a `foreach` statement. */ -private predicate mustHaveEmptinessCompletion(ControlFlowElement cfe) { - foreachEmptiness(_, cfe) -} +private predicate mustHaveEmptinessCompletion(ControlFlowElement cfe) { foreachEmptiness(_, cfe) } /** * A completion that represents normal evaluation of a statement or an @@ -456,9 +405,7 @@ abstract class NormalCompletion extends Completion { } * A class to make `TNormalCompletion` a `NormalCompletion` */ class SimpleCompletion extends NormalCompletion, TNormalCompletion { - override string toString() { - result = "normal" - } + override string toString() { result = "normal" } } /** @@ -480,20 +427,14 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion { /** Gets the value that this expression completes with. */ boolean getOuterValue() { this = TBooleanCompletion(result, _) } - override string toString() { - result = getOuterValue() + "/" + getInnerValue() - } + override string toString() { result = getOuterValue() + "/" + getInnerValue() } } /** A Boolean `true` completion. */ -class TrueCompletion extends BooleanCompletion { - TrueCompletion() { getOuterValue() = true } -} +class TrueCompletion extends BooleanCompletion { TrueCompletion() { getOuterValue() = true } } /** A Boolean `false` completion. */ -class FalseCompletion extends BooleanCompletion { - FalseCompletion() { getOuterValue() = false } -} +class FalseCompletion extends BooleanCompletion { FalseCompletion() { getOuterValue() = false } } /** * A completion that represents evaluation of an expression that is either @@ -503,12 +444,7 @@ class NullnessCompletion extends ConditionalCompletion, TNullnessCompletion { /** Holds if the last sub expression of this expression evaluates to `null`. */ predicate isNull() { this = TNullnessCompletion(true) } - override string toString() { - if this.isNull() then - result = "null" - else - result = "non-null" - } + override string toString() { if this.isNull() then result = "null" else result = "non-null" } } /** @@ -519,12 +455,7 @@ class MatchingCompletion extends ConditionalCompletion, TMatchingCompletion { /** Holds if there is a match. */ predicate isMatch() { this = TMatchingCompletion(true) } - override string toString() { - if this.isMatch() then - result = "match" - else - result = "no-match" - } + override string toString() { if this.isMatch() then result = "match" else result = "no-match" } } /** @@ -535,12 +466,7 @@ class EmptinessCompletion extends ConditionalCompletion, TEmptinessCompletion { /** Holds if the emptiness test evaluates to `true`. */ predicate isEmpty() { this = TEmptinessCompletion(true) } - override string toString() { - if this.isEmpty() then - result = "empty" - else - result = "non-empty" - } + override string toString() { if this.isEmpty() then result = "empty" else result = "non-empty" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll index 8738b5b3da8..89e9501995a 100644 --- a/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll +++ b/csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowElement.qll @@ -28,9 +28,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { * several `ControlFlow::Node`s, for example to represent the continuation * flow in a `try/catch/finally` construction. */ - Node getAControlFlowNode() { - result.getElement() = this - } + Node getAControlFlowNode() { result.getElement() = this } /** * Gets a first control flow node executed within this element. @@ -50,14 +48,10 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { * Holds if this element is live, that is this element can be reached * from the entry point of its enclosing callable. */ - predicate isLive() { - exists(this.getAControlFlowNode()) - } + predicate isLive() { exists(this.getAControlFlowNode()) } /** Holds if the current element is reachable from `src`. */ - predicate reachableFrom(ControlFlowElement src) { - this = src.getAReachableElement() - } + predicate reachableFrom(ControlFlowElement src) { this = src.getAReachableElement() } /** Gets an element that is reachable from this element. */ ControlFlowElement getAReachableElement() { @@ -96,11 +90,11 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { // Only calculate dominance by explicit recursion for split nodes; // all other nodes can use regular CFG dominance this instanceof ControlFlow::Internal::SplitControlFlowElement and - exists(ConditionBlock cb | - cb.getLastNode() = this.getAControlFlowNode() | + exists(ConditionBlock cb | cb.getLastNode() = this.getAControlFlowNode() | succ = cb.getASuccessorByType(s) and - forall(BasicBlock pred, SuccessorType t | - pred = succ.getAPredecessorByType(t) and pred != cb | + forall(BasicBlock pred, SuccessorType t | + pred = succ.getAPredecessorByType(t) and pred != cb + | succ.dominates(pred) or // `pred` might be another split of `cfe` @@ -112,9 +106,10 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { } pragma[nomagic] - private JoinBlockPredecessor getAPossiblyControlledPredecessor(JoinBlock controlled, ConditionalSuccessor s) { - exists(BasicBlock mid | - this.immediatelyControlsBlockSplit(mid, s) | + private JoinBlockPredecessor getAPossiblyControlledPredecessor( + JoinBlock controlled, ConditionalSuccessor s + ) { + exists(BasicBlock mid | this.immediatelyControlsBlockSplit(mid, s) | result = mid.getASuccessor*() ) and result.getASuccessor() = controlled and @@ -124,8 +119,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { pragma[nomagic] private predicate isPossiblyControlledJoinBlock(JoinBlock controlled, ConditionalSuccessor s) { exists(this.getAPossiblyControlledPredecessor(controlled, s)) and - forall(BasicBlock pred | - pred = controlled.getAPredecessor() | + forall(BasicBlock pred | pred = controlled.getAPredecessor() | pred = this.getAPossiblyControlledPredecessor(controlled, s) or controlled.dominates(pred) @@ -136,14 +130,13 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { private predicate controlsBlockSplit(BasicBlock controlled, ConditionalSuccessor s) { this.immediatelyControlsBlockSplit(controlled, s) or - if controlled instanceof JoinBlock then + if controlled instanceof JoinBlock + then this.isPossiblyControlledJoinBlock(controlled, s) and - forall(BasicBlock pred | - pred = this.getAPossiblyControlledPredecessor(controlled, s) | + forall(BasicBlock pred | pred = this.getAPossiblyControlledPredecessor(controlled, s) | this.controlsBlock(pred, s) ) - else - this.controlsBlockSplit(controlled.getAPredecessor(), s) + else this.controlsBlockSplit(controlled.getAPredecessor(), s) } /** @@ -166,8 +159,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { predicate controlsBlock(BasicBlock controlled, ConditionalSuccessor s) { this.controlsBlockSplit(controlled, s) or - exists(ConditionBlock cb | - cb.getLastNode() = this.getAControlFlowNode() | + exists(ConditionBlock cb | cb.getLastNode() = this.getAControlFlowNode() | cb.controls(controlled, s) ) } @@ -188,10 +180,10 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element { * * as control flow splitting is taken into account. */ - pragma[inline] // potentially very large predicate, so must be inlined + // potentially very large predicate, so must be inlined + pragma[inline] predicate controlsElement(ControlFlowElement controlled, ConditionalSuccessor s) { - forex(BasicBlock bb | - bb = controlled.getAControlFlowNode().getBasicBlock() | + forex(BasicBlock bb | bb = controlled.getAControlFlowNode().getBasicBlock() | this.controlsBlock(bb, s) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll b/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll index b57398812a9..70c5ae93790 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/CallContext.qll @@ -7,17 +7,11 @@ private import semmle.code.csharp.dataflow.DelegateDataFlow private import dotnet // Internal representation of call contexts -cached private newtype TCallContext = - TEmptyCallContext() - or - TArgCallContext(DotNet::Call c, int i) { - exists(c.getArgument(i)) - } - or - TDynamicAccessorArgCallContext(DynamicAccessorCall dac, int i) { - exists(dac.getArgument(i)) - } - or +cached +private newtype TCallContext = + TEmptyCallContext() or + TArgCallContext(DotNet::Call c, int i) { exists(c.getArgument(i)) } or + TDynamicAccessorArgCallContext(DynamicAccessorCall dac, int i) { exists(dac.getArgument(i)) } or TDelegateToLibraryCallableArgCallContext(DelegateArgumentToLibraryCallable arg, int i) { exists(arg.getDelegateType().getParameter(i)) } @@ -55,47 +49,37 @@ abstract class ArgumentCallContext extends CallContext { /** An argument of an ordinary call. */ class CallArgumentCallContext extends ArgumentCallContext, TArgCallContext { DotNet::Call c; + int arg; - CallArgumentCallContext() { - this = TArgCallContext(c, arg) - } + CallArgumentCallContext() { this = TArgCallContext(c, arg) } override predicate isArgument(DotNet::Expr call, int i) { call = c and i = arg } - override string toString() { - result = c.getArgument(arg).toString() - } + override string toString() { result = c.getArgument(arg).toString() } - override Location getLocation() { - result = c.getArgument(arg).getLocation() - } + override Location getLocation() { result = c.getArgument(arg).getLocation() } } /** An argument of a dynamic accessor call. */ class DynamicAccessorArgumentCallContext extends ArgumentCallContext, TDynamicAccessorArgCallContext { DynamicAccessorCall dac; + int arg; - DynamicAccessorArgumentCallContext() { - this = TDynamicAccessorArgCallContext(dac, arg) - } + DynamicAccessorArgumentCallContext() { this = TDynamicAccessorArgCallContext(dac, arg) } override predicate isArgument(DotNet::Expr call, int i) { call = dac and i = arg } - override string toString() { - result = dac.getArgument(arg).toString() - } + override string toString() { result = dac.getArgument(arg).toString() } - override Location getLocation() { - result = dac.getArgument(arg).getLocation() - } + override Location getLocation() { result = dac.getArgument(arg).getLocation() } } /** @@ -107,8 +91,10 @@ class DynamicAccessorArgumentCallContext extends ArgumentCallContext, TDynamicAc * in the database, so the delegate argument `y => y` is used to * represent the call. */ -class DelegateArgumentToLibraryCallableArgumentContext extends ArgumentCallContext, TDelegateToLibraryCallableArgCallContext { +class DelegateArgumentToLibraryCallableArgumentContext extends ArgumentCallContext, + TDelegateToLibraryCallableArgCallContext { DotNet::Expr delegate; + int arg; DelegateArgumentToLibraryCallableArgumentContext() { @@ -120,11 +106,7 @@ class DelegateArgumentToLibraryCallableArgumentContext extends ArgumentCallConte i = arg } - override string toString() { - result = "argument " + arg + " of " + delegate.toString() - } + override string toString() { result = "argument " + arg + " of " + delegate.toString() } - override Location getLocation() { - result = delegate.getLocation() - } + override Location getLocation() { result = delegate.getLocation() } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/DelegateDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/DelegateDataFlow.qll index fdd0428376b..a8da58aba3f 100755 --- a/csharp/ql/src/semmle/code/csharp/dataflow/DelegateDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/DelegateDataFlow.qll @@ -16,19 +16,17 @@ private class DelegateFlowSource extends DataFlow::ExprNode { DelegateFlowSource() { this.getExpr() = any(Expr e | - c = e.(AnonymousFunctionExpr) or - c = e.(CallableAccess).getTarget().getSourceDeclaration() - ) + c = e.(AnonymousFunctionExpr) or + c = e.(CallableAccess).getTarget().getSourceDeclaration() + ) } /** Gets the callable that is referenced in this delegate flow source. */ - Callable getCallable() { - result = c - } + Callable getCallable() { result = c } } /** A sink of flow for a delegate expression. */ -private abstract class DelegateFlowSink extends DataFlow::ExprNode { +abstract private class DelegateFlowSink extends DataFlow::ExprNode { /** * Gets an actual run-time target of this delegate call in the given call * context, if any. The call context records the *last* call required to @@ -93,19 +91,16 @@ private abstract class DelegateFlowSink extends DataFlow::ExprNode { library class DelegateCallExpr extends DelegateFlowSink { DelegateCall dc; - DelegateCallExpr() { - this.getExpr() = dc.getDelegateExpr() - } + DelegateCallExpr() { this.getExpr() = dc.getDelegateExpr() } /** Gets the delegate call that this expression belongs to. */ - DelegateCall getDelegateCall() { - result = dc - } + DelegateCall getDelegateCall() { result = dc } } /** A delegate expression that is passed as the argument to a library callable. */ library class DelegateArgumentToLibraryCallable extends Expr { DelegateType dt; + Call call; DelegateArgumentToLibraryCallable() { @@ -118,14 +113,10 @@ library class DelegateArgumentToLibraryCallable extends Expr { } /** Gets the call that this argument belongs to. */ - Call getCall() { - result = call - } + Call getCall() { result = call } /** Gets the delegate type of this argument. */ - DelegateType getDelegateType() { - result = dt - } + DelegateType getDelegateType() { result = dt } /** * Gets an actual run-time target of this delegate call in the given call @@ -133,8 +124,7 @@ library class DelegateArgumentToLibraryCallable extends Expr { * resolve the target, if any. Example: */ Callable getARuntimeTarget(CallContext context) { - exists(DelegateArgumentToLibraryCallableSink sink | - sink.getExpr() = this | + exists(DelegateArgumentToLibraryCallableSink sink | sink.getExpr() = this | result = sink.getARuntimeTarget(context) ) } @@ -151,14 +141,10 @@ private class DelegateArgumentToLibraryCallableSink extends DelegateFlowSink { library class AddEventSource extends DelegateFlowSink { AddEventExpr ae; - AddEventSource() { - this.getExpr() = ae.getRValue() - } + AddEventSource() { this.getExpr() = ae.getRValue() } /** Gets the event that this delegate is added to. */ - Event getEvent() { - result = ae.getTarget() - } + Event getEvent() { result = ae.getTarget() } } /** @@ -169,15 +155,16 @@ library class AddEventSource extends DelegateFlowSink { * `node` goes through a returned expression. The call context `lastCall` * records the last call on the path from `node` to `sink`, if any. */ -private predicate flowsFrom(DelegateFlowSink sink, DataFlow::Node node, boolean isReturned, CallContext lastCall) { +private predicate flowsFrom( + DelegateFlowSink sink, DataFlow::Node node, boolean isReturned, CallContext lastCall +) { // Base case sink = node and isReturned = false and lastCall instanceof EmptyCallContext or // Local flow - exists(DataFlow::Node mid | - flowsFrom(sink, mid, isReturned, lastCall) | + exists(DataFlow::Node mid | flowsFrom(sink, mid, isReturned, lastCall) | DataFlow::localFlowStep(node, mid) or node.asExpr() = mid.asExpr().(DelegateCreation).getArgument() ) @@ -191,7 +178,9 @@ private predicate flowsFrom(DelegateFlowSink sink, DataFlow::Node node, boolean ) or // Flow into a callable (non-delegate call) - exists(DataFlow::Internal::ExplicitParameterNode mid, CallContext prevLastCall, Expr call, Parameter p | + exists( + DataFlow::Internal::ExplicitParameterNode mid, CallContext prevLastCall, Expr call, Parameter p + | flowsFrom(sink, mid, isReturned, prevLastCall) and isReturned = false and p = mid.getParameter() and @@ -200,7 +189,10 @@ private predicate flowsFrom(DelegateFlowSink sink, DataFlow::Node node, boolean ) or // Flow into a callable (delegate call) - exists(DataFlow::Internal::ExplicitParameterNode mid, CallContext prevLastCall, DelegateCall dc, Callable c, Parameter p, int i | + exists( + DataFlow::Internal::ExplicitParameterNode mid, CallContext prevLastCall, DelegateCall dc, + Callable c, Parameter p, int i + | flowsFrom(sink, mid, isReturned, prevLastCall) and isReturned = false and flowIntoDelegateCall(dc, c, node.asExpr(), i) and @@ -229,7 +221,7 @@ private predicate flowsFrom(DelegateFlowSink sink, DataFlow::Node node, boolean * `prevLastCall` is the previous last call, so the result is the * previous call if it exists, otherwise `call` is the last call. */ -bindingset [call, i] +bindingset[call, i] private CallContext getLastCall(CallContext prevLastCall, Expr call, int i) { prevLastCall instanceof EmptyCallContext and result.(ArgumentCallContext).isArgument(call, i) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index d5debe55cfe..3f02da60de3 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -17,14 +17,16 @@ private import semmle.code.csharp.frameworks.system.Web private import semmle.code.csharp.frameworks.system.web.ui.WebControls private import semmle.code.csharp.frameworks.system.Xml -private cached module Cached { +cached +private module Cached { /** * INTERNAL: Do not use. * * Holds if `source` can flow to `sink` using a call to a library * callable. */ - cached predicate libraryFlow(Expr source, Expr sink, boolean preservesValue) { + cached + predicate libraryFlow(Expr source, Expr sink, boolean preservesValue) { exists(LibraryTypeDataFlow ltdf, CallableFlowSource csource, CallableFlowSink csink, Call c | source = csource.getSource(c) and ltdf.callableFlow(csource, csink, c.getTarget().getSourceDeclaration(), preservesValue) and @@ -38,7 +40,8 @@ private cached module Cached { * Holds if `source` can flow to the `out`/`ref` argument `outRef` using a call to a library * callable. */ - cached predicate libraryFlowOutRef(MethodCall mc, Expr source, Parameter outRef, boolean preservesValue) { + cached + predicate libraryFlowOutRef(MethodCall mc, Expr source, Parameter outRef, boolean preservesValue) { exists(LibraryTypeDataFlow ltdf, CallableFlowSource csource, CallableFlowSinkArg csink | source = csource.getSource(mc) and mc.getTarget().getAParameter() = outRef and @@ -62,7 +65,10 @@ private cached module Cached { * Holds if output from the `i`th delegate argument of `call` can flow to `sink`, using * the library target `callable`. */ - cached predicate libraryFlowDelegateCallOut(Call call, Callable callable, Expr sink, boolean preservesValue, int i) { + cached + predicate libraryFlowDelegateCallOut( + Call call, Callable callable, Expr sink, boolean preservesValue, int i + ) { exists(LibraryTypeDataFlow ltdf, CallableFlowSourceDelegateArg csource, CallableFlowSink csink | ltdf.callableFlow(csource, csink, callable, preservesValue) and call.getTarget().getSourceDeclaration() = callable and @@ -79,7 +85,10 @@ private cached module Cached { * `j`. The call `call` is the call in which `sink` is an argument and`callable` * is the library target. */ - cached predicate libraryFlowDelegateCallIn(Call call, Callable callable, Expr source, boolean preservesValue, int i, int j) { + cached + predicate libraryFlowDelegateCallIn( + Call call, Callable callable, Expr source, boolean preservesValue, int i, int j + ) { exists(LibraryTypeDataFlow ltdf, CallableFlowSource csource, CallableFlowSinkDelegateArg csink | ltdf.callableFlow(csource, csink, callable, preservesValue) and call.getTarget().getSourceDeclaration() = callable and @@ -96,8 +105,14 @@ private cached module Cached { * Holds if output from the `i`th delegate argument of `call` can flow to the `j`th parameter * of the of delegate at argument `k`, using the library target `callable`. */ - cached predicate libraryFlowDelegateCallOutIn(Call call, Callable callable, boolean preservesValue, int i, int j, int k) { - exists(LibraryTypeDataFlow ltdf, CallableFlowSourceDelegateArg csource, CallableFlowSinkDelegateArg csink | + cached + predicate libraryFlowDelegateCallOutIn( + Call call, Callable callable, boolean preservesValue, int i, int j, int k + ) { + exists( + LibraryTypeDataFlow ltdf, CallableFlowSourceDelegateArg csource, + CallableFlowSinkDelegateArg csink + | ltdf.callableFlow(csource, csink, callable, preservesValue) and call.getTarget().getSourceDeclaration() = callable and csource.getCallable() = callable and @@ -112,9 +127,7 @@ import Cached /** An unbound callable. */ library class SourceDeclarationCallable extends Callable { - SourceDeclarationCallable() { - this = getSourceDeclaration() - } + SourceDeclarationCallable() { this = getSourceDeclaration() } } /** An unbound method. */ @@ -122,25 +135,25 @@ library class SourceDeclarationMethod extends SourceDeclarationCallable, Method // Internal representation of callable flow sources private newtype TCallableFlowSource = - TCallableFlowSourceQualifier() - or + TCallableFlowSourceQualifier() or TCallableFlowSourceArg(SourceDeclarationCallable callable, int i) { exists(int arity | - if callable.getAParameter().isParams() then + if callable.getAParameter().isParams() + then arity = max(Call call | - call.getTarget().getSourceDeclaration() = callable | - call.getNumberOfArguments() - ) - else - arity = callable.getNumberOfParameters() - | + call.getTarget().getSourceDeclaration() = callable + | + call.getNumberOfArguments() + ) + else arity = callable.getNumberOfParameters() + | i in [0 .. arity - 1] ) - } - or + } or TCallableFlowSourceDelegateArg(SourceDeclarationCallable c, int i) { exists(DelegateType dt | - dt = c.getParameter(i).getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() | + dt = c.getParameter(i).getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() + | not dt.getReturnType() instanceof VoidType ) } @@ -158,33 +171,23 @@ class CallableFlowSource extends TCallableFlowSource { class CallableFlowSourceQualifier extends CallableFlowSource, TCallableFlowSourceQualifier { override string toString() { result = "qualifier" } - override Expr getSource(Call c) { - result = c.getChild(-1) - } + override Expr getSource(Call c) { result = c.getChild(-1) } } /** A flow source in a call to a library callable: argument. */ class CallableFlowSourceArg extends CallableFlowSource, TCallableFlowSourceArg { override string toString() { - exists(int i | - this = TCallableFlowSourceArg(_, i) | - result = "argument " + i.toString() - ) + exists(int i | this = TCallableFlowSourceArg(_, i) | result = "argument " + i.toString()) } /** Gets the callable containing this flow source. */ - Callable getCallable() { - this = TCallableFlowSourceArg(result, _) - } + Callable getCallable() { this = TCallableFlowSourceArg(result, _) } /** Gets the index of this argument. */ - int getArgumentIndex() { - this = TCallableFlowSourceArg(_, result) - } + int getArgumentIndex() { this = TCallableFlowSourceArg(_, result) } override Expr getSource(Call c) { - exists(int i | - this = TCallableFlowSourceArg(c.getTarget().getSourceDeclaration(), i) | + exists(int i | this = TCallableFlowSourceArg(c.getTarget().getSourceDeclaration(), i) | result = c.getArgument(i) ) } @@ -193,40 +196,29 @@ class CallableFlowSourceArg extends CallableFlowSource, TCallableFlowSourceArg { /** A flow source in a call to a library callable: output from delegate argument. */ class CallableFlowSourceDelegateArg extends CallableFlowSource, TCallableFlowSourceDelegateArg { override string toString() { - exists(int i | - this = TCallableFlowSourceDelegateArg(_, i) | + exists(int i | this = TCallableFlowSourceDelegateArg(_, i) | result = "output from argument " + i.toString() ) } /** Gets the callable containing this flow source. */ - Callable getCallable() { - this = TCallableFlowSourceDelegateArg(result, _) - } + Callable getCallable() { this = TCallableFlowSourceDelegateArg(result, _) } /** Gets the index of this delegate argument. */ - int getArgumentIndex() { - this = TCallableFlowSourceDelegateArg(_, result) - } + int getArgumentIndex() { this = TCallableFlowSourceDelegateArg(_, result) } - override Expr getSource(Call c) { - none() - } + override Expr getSource(Call c) { none() } } // Internal representation of callable flow sinks private newtype TCallableFlowSink = - TCallableFlowSinkQualifier() - or - TCallableFlowSinkReturn() - or - TCallableFlowSinkArg(SourceDeclarationCallable c, int i) { - exists(c.getParameter(i)) - } - or + TCallableFlowSinkQualifier() or + TCallableFlowSinkReturn() or + TCallableFlowSinkArg(SourceDeclarationCallable c, int i) { exists(c.getParameter(i)) } or TCallableFlowSinkDelegateArg(SourceDeclarationCallable c, int i, int j) { exists(DelegateType dt | - dt = c.getParameter(i).getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() | + dt = c.getParameter(i).getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() + | exists(dt.getParameter(j)) ) } @@ -244,38 +236,27 @@ class CallableFlowSink extends TCallableFlowSink { class CallableFlowSinkQualifier extends CallableFlowSink, TCallableFlowSinkQualifier { override string toString() { result = "qualifier" } - override Expr getSink(Call c) { - result = c.getChild(-1) - } + override Expr getSink(Call c) { result = c.getChild(-1) } } /** A flow sink in a call to a library callable: return value. */ class CallableFlowSinkReturn extends CallableFlowSink, TCallableFlowSinkReturn { override string toString() { result = "return" } - override Expr getSink(Call c) { - result = c - } + override Expr getSink(Call c) { result = c } } /** The flow sink in an argument to a call to a library method. */ class CallableFlowSinkArg extends CallableFlowSink, TCallableFlowSinkArg { override string toString() { - exists(int i | - this = TCallableFlowSinkArg(_, i) | - result = "argument " + i.toString() - ) + exists(int i | this = TCallableFlowSinkArg(_, i) | result = "argument " + i.toString()) } /** Gets the callable containing this flow sink. */ - Callable getCallable() { - this = TCallableFlowSinkArg(result, _) - } + Callable getCallable() { this = TCallableFlowSinkArg(result, _) } /** Gets the index of this `out`/`ref` argument. */ - int getArgumentIndex() { - this = TCallableFlowSinkArg(_, result) - } + int getArgumentIndex() { this = TCallableFlowSinkArg(_, result) } override Expr getSink(Call c) { // The uses of the `i`th argument are the actual sinks @@ -286,8 +267,7 @@ class CallableFlowSinkArg extends CallableFlowSink, TCallableFlowSinkArg { /** The flow sink in a call to a library callable: parameter of a delegate argument. */ class CallableFlowSinkDelegateArg extends CallableFlowSink, TCallableFlowSinkDelegateArg { override string toString() { - exists(int i, int j | - this = TCallableFlowSinkDelegateArg(_, i, j) | + exists(int i, int j | this = TCallableFlowSinkDelegateArg(_, i, j) | result = "parameter " + j.toString() + " of argument " + i.toString() ) } @@ -298,28 +278,20 @@ class CallableFlowSinkDelegateArg extends CallableFlowSink, TCallableFlowSinkDel } /** Gets the callable containing this flow sink. */ - Callable getCallable() { - this = TCallableFlowSinkDelegateArg(result, _, _) - } + Callable getCallable() { this = TCallableFlowSinkDelegateArg(result, _, _) } /** Gets the index of the delegate argument. */ - int getDelegateIndex() { - this = TCallableFlowSinkDelegateArg(_, result, _) - } + int getDelegateIndex() { this = TCallableFlowSinkDelegateArg(_, result, _) } /** Gets the index of the delegate parameter. */ - int getDelegateParameterIndex() { - this = TCallableFlowSinkDelegateArg(_, _, result) - } + int getDelegateParameterIndex() { this = TCallableFlowSinkDelegateArg(_, _, result) } } /** * A specification of data flow for a library (non-source code) type. */ abstract class LibraryTypeDataFlow extends Type { - LibraryTypeDataFlow() { - this = getSourceDeclaration() - } + LibraryTypeDataFlow() { this = getSourceDeclaration() } /** * Holds if data may flow from `source` to `sink` when calling callable `c`. @@ -328,50 +300,61 @@ abstract class LibraryTypeDataFlow extends Type { * (possibly copied) to `sink`. For example, the value is preserved from `x` * to `x.ToString()` when `x` is a `string`, but not from `x` to `x.ToLower()`. */ - pragma [nomagic] - abstract predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue); + pragma[nomagic] + abstract predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ); } /** Data flow for `System.Int32`. */ class SystemInt32Flow extends LibraryTypeDataFlow, SystemInt32Struct { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { methodFlow(source, sink, c) and preservesValue = false } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - ( - m = getParseMethod() and - source = TCallableFlowSourceArg(m, 0) and - sink = TCallableFlowSinkReturn() - ) + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m = getParseMethod() and + source = TCallableFlowSourceArg(m, 0) and + sink = TCallableFlowSinkReturn() or + m = getTryParseMethod() and + source = TCallableFlowSourceArg(m, 0) and ( - m = getTryParseMethod() and - source = TCallableFlowSourceArg(m, 0) and - ( - sink = TCallableFlowSinkReturn() - or - sink = TCallableFlowSinkArg(m, any(int i | m.getParameter(i).isOutOrRef())) - ) + sink = TCallableFlowSinkReturn() + or + sink = TCallableFlowSinkArg(m, any(int i | m.getParameter(i).isOutOrRef())) ) } } /** Data flow for `System.Boolean`. */ class SystemBooleanFlow extends LibraryTypeDataFlow, SystemBooleanStruct { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { methodFlow(source, sink, c) and preservesValue = false } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m = getParseMethod() and ( + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m = getParseMethod() and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - m = getTryParseMethod() and ( + m = getTryParseMethod() and + ( source = TCallableFlowSourceArg(m, 0) and ( sink = TCallableFlowSinkReturn() @@ -384,7 +367,10 @@ class SystemBooleanFlow extends LibraryTypeDataFlow, SystemBooleanStruct { /** Data flow for `System.Uri`. */ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or @@ -396,28 +382,23 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass { sink = TCallableFlowSinkReturn() and c = p.getGetter() ) - ) - and + ) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() - and - c.getParameter(0).getType() instanceof StringType - and - source = TCallableFlowSourceArg(c, 0) - and + c = getAMember() and + c.getParameter(0).getType() instanceof StringType and + source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m.getDeclaringType() = getABaseType*() - and - m = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() - and - source = TCallableFlowSourceQualifier() - and + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m.getDeclaringType() = getABaseType*() and + m = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() and + source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() } @@ -432,70 +413,74 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass { /** Data flow for `System.IO.StringReader`. */ class SystemIOStringReaderFlow extends LibraryTypeDataFlow, SystemIOStringReaderClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or methodFlow(source, sink, c) - ) - and + ) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() - and - c.getParameter(0).getType() instanceof StringType - and - source = TCallableFlowSourceArg(c, 0) - and + c = getAMember() and + c.getParameter(0).getType() instanceof StringType and + source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m.getDeclaringType() = getABaseType*() - and - m.getName().matches("Read%") - and - source = TCallableFlowSourceQualifier() - and + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m.getDeclaringType() = getABaseType*() and + m.getName().matches("Read%") and + source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() } } /** Data flow for `System.String`. */ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { constructorFlow(source, sink, c) and preservesValue = false or methodFlow(source, sink, c, preservesValue) } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() - and - c.getParameter(0).getType().(ArrayType).getElementType() instanceof CharType - and - source = TCallableFlowSourceArg(c, 0) - and + c = getAMember() and + c.getParameter(0).getType().(ArrayType).getElementType() instanceof CharType and + source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m, boolean preservesValue) { - m = getAMethod() and ( + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m, + boolean preservesValue + ) { + m = getAMethod() and + ( m = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = true ) or - m = getSplitMethod() and ( + m = getSplitMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getReplaceMethod() and ( + m = getReplaceMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false @@ -505,19 +490,22 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { preservesValue = false ) or - m = getSubstringMethod() and ( + m = getSubstringMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getCloneMethod() and ( + m = getCloneMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = true ) or - m = getInsertMethod() and ( + m = getInsertMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false @@ -527,44 +515,53 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { preservesValue = false ) or - m = getNormalizeMethod() and ( + m = getNormalizeMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getRemoveMethod() and ( + m = getRemoveMethod() and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getAMethod() and ( - m.getName().regexpMatch("((ToLower|ToUpper)(Invariant)?)|(Trim(Start|End)?)|(Pad(Left|Right))") and + m = getAMethod() and + ( + m + .getName() + .regexpMatch("((ToLower|ToUpper)(Invariant)?)|(Trim(Start|End)?)|(Pad(Left|Right))") and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getConcatMethod() and ( + m = getConcatMethod() and + ( source = TCallableFlowSourceArg(m, _) and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getCopyMethod() and ( + m = getCopyMethod() and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() and preservesValue = true ) or - m = getJoinMethod() and ( + m = getJoinMethod() and + ( source = TCallableFlowSourceArg(m, _) and sink = TCallableFlowSinkReturn() and preservesValue = false ) or - m = getFormatMethod() and exists(int i | + m = getFormatMethod() and + exists(int i | (m.getParameter(0).getType() instanceof SystemIFormatProviderInterface implies i != 0) and source = TCallableFlowSourceArg(m, i) and sink = TCallableFlowSinkReturn() and @@ -575,38 +572,42 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass { /** Data flow for `System.Text.StringBuilder`. */ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringBuilderClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or methodFlow(source, sink, c) - ) - and + ) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() - and - c.getParameter(0).getType() instanceof StringType - and - source = TCallableFlowSourceArg(c, 0) - and + c = getAMember() and + c.getParameter(0).getType() instanceof StringType and + source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m.getDeclaringType() = getABaseType*() and ( + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m.getDeclaringType() = getABaseType*() and + ( m = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() ) or - m = getAMethod() and exists(int i, Type t | + m = getAMethod() and + exists(int i, Type t | m.getName().regexpMatch("Append(Format|Line)?") and t = m.getParameter(i).getType() and source = TCallableFlowSourceArg(m, i) and - sink = TCallableFlowSinkQualifier() | + sink = TCallableFlowSinkQualifier() + | t instanceof StringType or t instanceof ObjectType ) @@ -615,11 +616,12 @@ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringB /** Data flow for `System.Lazy<>`. */ class SystemLazyFlow extends LibraryTypeDataFlow { - SystemLazyFlow() { - this instanceof SystemLazyClass - } + SystemLazyFlow() { this instanceof SystemLazyClass } - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or @@ -629,27 +631,22 @@ class SystemLazyFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() and c = p.getGetter() ) - ) - and + ) and preservesValue = true } - private predicate constructorFlow(CallableFlowSourceDelegateArg source, CallableFlowSink sink, Constructor c) { - exists(SystemFuncDelegateType t, int i | - t.getNumberOfTypeParameters() = 1 | - c.getDeclaringType() = this - and - c.getParameter(i).getType().getSourceDeclaration() = t - and - source = TCallableFlowSourceDelegateArg(c, i) - and + private predicate constructorFlow( + CallableFlowSourceDelegateArg source, CallableFlowSink sink, Constructor c + ) { + exists(SystemFuncDelegateType t, int i | t.getNumberOfTypeParameters() = 1 | + c.getDeclaringType() = this and + c.getParameter(i).getType().getSourceDeclaration() = t and + source = TCallableFlowSourceDelegateArg(c, i) and sink = TCallableFlowSinkReturn() ) } - private predicate propertyFlow(Property p) { - p = this.(SystemLazyClass).getValueProperty() - } + private predicate propertyFlow(Property p) { p = this.(SystemLazyClass).getValueProperty() } } /** @@ -658,17 +655,20 @@ class SystemLazyFlow extends LibraryTypeDataFlow { */ class IEnumerableFlow extends LibraryTypeDataFlow { IEnumerableFlow() { - exists(RefType t | - t = this.(RefType).getABaseType*() | + exists(RefType t | t = this.(RefType).getABaseType*() | t instanceof SystemCollectionsIEnumerableInterface or t instanceof SystemCollectionsGenericIEnumerableTInterface or - t.(ConstructedInterface).getUnboundGeneric() instanceof SystemCollectionsGenericIEnumerableTInterface + t.(ConstructedInterface).getUnboundGeneric() instanceof + SystemCollectionsGenericIEnumerableTInterface ) } - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( methodFlow(source, sink, c) or @@ -678,25 +678,28 @@ class IEnumerableFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() and c = p.getGetter() ) - ) - and + ) and preservesValue = false } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { methodFlowLINQ(source, sink, m) or methodFlowSpecific(source, sink, m) } /** Flow for LINQ methods. */ - private predicate methodFlowLINQ(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m.(ExtensionMethod).getExtendedType().getSourceDeclaration() = this - and - exists(string name, int arity | - name = m.getName() and arity = m.getNumberOfParameters() | - name = "Aggregate" and ( - arity = 2 and ( + private predicate methodFlowLINQ( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m.(ExtensionMethod).getExtendedType().getSourceDeclaration() = this and + exists(string name, int arity | name = m.getName() and arity = m.getNumberOfParameters() | + name = "Aggregate" and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 1) or @@ -704,7 +707,8 @@ class IEnumerableFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() ) or - arity = 3 and ( + arity = 3 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 2, 1) or @@ -715,7 +719,8 @@ class IEnumerableFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() ) or - arity = 4 and ( + arity = 4 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 2, 1) or @@ -730,38 +735,45 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "All" and ( + name = "All" and + ( arity = 2 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) or - name = "Any" and ( + name = "Any" and + ( arity = 2 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) or - name = "AsEnumerable" and ( + name = "AsEnumerable" and + ( arity = 1 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - name = "Average" and ( + name = "Average" and + ( arity = 2 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) or - name = "Cast" and ( + name = "Cast" and + ( arity = 1 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - name = "Concat" and ( - arity = 2 and ( + name = "Concat" and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() or @@ -770,13 +782,15 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name.regexpMatch("(Long)?Count") and ( + name.regexpMatch("(Long)?Count") and + ( arity = 2 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) or - name = "DefaultIfEmpty" and ( + name = "DefaultIfEmpty" and + ( arity in [1 .. 2] and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() @@ -786,38 +800,46 @@ class IEnumerableFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() ) or - name = "Distinct" and ( + name = "Distinct" and + ( arity in [1 .. 2] and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - name.regexpMatch("ElementAt(OrDefault)?") and ( + name.regexpMatch("ElementAt(OrDefault)?") and + ( arity = 2 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - name = "Except" and ( + name = "Except" and + ( arity in [2 .. 3] and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - name.regexpMatch("(First|Single)(OrDefault)?") and ( - arity in [1 .. 2] and ( + name.regexpMatch("(First|Single)(OrDefault)?") and + ( + arity in [1 .. 2] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - arity = 2 and ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) ) or - name = "GroupBy" and ( - arity = 3 and ( + name = "GroupBy" and + ( + arity = 3 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -833,16 +855,19 @@ class IEnumerableFlow extends LibraryTypeDataFlow { source = TCallableFlowSourceDelegateArg(m, 1) and sink = TCallableFlowSinkDelegateArg(m, 2, 0) or - not m.getParameter(2).getType().getSourceDeclaration() instanceof SystemCollectionsGenericIEqualityComparerTInterface and + not m.getParameter(2).getType().getSourceDeclaration() instanceof + SystemCollectionsGenericIEqualityComparerTInterface and source = TCallableFlowSourceDelegateArg(m, 2) and sink = TCallableFlowSinkReturn() or - m.getParameter(2).getType().getSourceDeclaration() instanceof SystemCollectionsGenericIEqualityComparerTInterface and + m.getParameter(2).getType().getSourceDeclaration() instanceof + SystemCollectionsGenericIEqualityComparerTInterface and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - arity in [4 .. 5] and ( + arity in [4 .. 5] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -860,8 +885,10 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name.regexpMatch("(Group)?Join") and ( - arity in [5 .. 6] and ( + name.regexpMatch("(Group)?Join") and + ( + arity in [5 .. 6] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 2, 0) or @@ -879,8 +906,10 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "Intersect" and ( - arity in [2 .. 3] and ( + name = "Intersect" and + ( + arity in [2 .. 3] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() or @@ -889,34 +918,43 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name.regexpMatch("Last(OrDefault)?") and ( - arity in [1 .. 2] and ( + name.regexpMatch("Last(OrDefault)?") and + ( + arity in [1 .. 2] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - arity = 2 and ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) ) or - name.regexpMatch("Max|Min|Sum") and ( - arity = 2 and ( + name.regexpMatch("Max|Min|Sum") and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) ) or - name = "OfType" and ( - arity = 1 and ( + name = "OfType" and + ( + arity = 1 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) ) or - name.regexpMatch("OrderBy(Descending)?") and ( - arity in [2 .. 3] and ( + name.regexpMatch("OrderBy(Descending)?") and + ( + arity in [2 .. 3] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() or @@ -925,22 +963,28 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "Repeat" and ( - arity = 2 and ( + name = "Repeat" and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) ) or - name = "Reverse" and ( - arity = 1 and ( + name = "Reverse" and + ( + arity = 1 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) ) or - name.regexpMatch("Select(Many)?") and ( - arity = 2 and ( + name.regexpMatch("Select(Many)?") and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -949,8 +993,10 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "SelectMany" and ( - arity = 3 and ( + name = "SelectMany" and + ( + arity = 3 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -965,22 +1011,28 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name.regexpMatch("(Skip|Take)(While)?") and ( - arity = 2 and ( + name.regexpMatch("(Skip|Take)(While)?") and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) ) or - name.regexpMatch("(Skip|Take)While") and ( - arity = 2 and ( + name.regexpMatch("(Skip|Take)While") and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) ) or - name.regexpMatch("ThenBy(Descending)?") and ( - arity in [2 .. 3] and ( + name.regexpMatch("ThenBy(Descending)?") and + ( + arity in [2 .. 3] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -989,15 +1041,19 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name.regexpMatch("To(Array|List)") and ( - arity = 1 and ( + name.regexpMatch("To(Array|List)") and + ( + arity = 1 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) ) or - name.regexpMatch("To(Dictionary|Lookup)") and ( - arity in [2 .. 3] and ( + name.regexpMatch("To(Dictionary|Lookup)") and + ( + arity in [2 .. 3] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -1006,7 +1062,8 @@ class IEnumerableFlow extends LibraryTypeDataFlow { not m.getParameter(2).getType() instanceof DelegateType ) or - arity in [3 .. 4] and ( + arity in [3 .. 4] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -1018,8 +1075,10 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "Union" and ( - arity in [2 .. 3] and ( + name = "Union" and + ( + arity in [2 .. 3] and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() or @@ -1028,8 +1087,10 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "Where" and ( - arity = 2 and ( + name = "Where" and + ( + arity = 2 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 1, 0) or @@ -1038,8 +1099,10 @@ class IEnumerableFlow extends LibraryTypeDataFlow { ) ) or - name = "Zip" and ( - arity = 3 and ( + name = "Zip" and + ( + arity = 3 and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkDelegateArg(m, 2, 0) or @@ -1054,18 +1117,19 @@ class IEnumerableFlow extends LibraryTypeDataFlow { } /** Flow for specific enumerables (e.g., `List` and `Stack`). */ - private predicate methodFlowSpecific(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { + private predicate methodFlowSpecific( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { m = getFind() and - if m.isStatic() then - source = TCallableFlowSourceArg(m, 0) - and + if m.isStatic() + then + source = TCallableFlowSourceArg(m, 0) and ( sink = TCallableFlowSinkReturn() or sink = TCallableFlowSinkDelegateArg(m, 1, 0) ) else ( - source = TCallableFlowSourceQualifier() - and + source = TCallableFlowSourceQualifier() and ( sink = TCallableFlowSinkReturn() or sink = TCallableFlowSinkDelegateArg(m, 0, 0) @@ -1075,30 +1139,37 @@ class IEnumerableFlow extends LibraryTypeDataFlow { exists(string name, int arity | name = m.getName() and arity = m.getNumberOfParameters() and - m.getDeclaringType() = this.(RefType).getABaseType*() | - name = "FixedSize" and ( + m.getDeclaringType() = this.(RefType).getABaseType*() + | + name = "FixedSize" and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - name.regexpMatch("GetByIndex|Peek|Pop|AsReadOnly|Clone|GetRange|MemberwiseClone|Reverse|GetEnumerator|GetValueList") and ( + name + .regexpMatch("GetByIndex|Peek|Pop|AsReadOnly|Clone|GetRange|MemberwiseClone|Reverse|GetEnumerator|GetValueList") and + ( source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() ) or - name.regexpMatch("Add(Range)?") and ( + name.regexpMatch("Add(Range)?") and + ( arity = 1 and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkQualifier() ) or - name = "Add" and ( + name = "Add" and + ( arity = 2 and source = TCallableFlowSourceArg(m, 1) and sink = TCallableFlowSinkQualifier() ) or - name.regexpMatch("Insert(Range)?") and ( + name.regexpMatch("Insert(Range)?") and + ( not this instanceof StringType and arity = 2 and source = TCallableFlowSourceArg(m, 1) and @@ -1110,26 +1181,31 @@ class IEnumerableFlow extends LibraryTypeDataFlow { private SourceDeclarationMethod getFind() { exists(string name | name = result.getName() and - result.getDeclaringType() = this.(RefType).getABaseType*() | + result.getDeclaringType() = this.(RefType).getABaseType*() + | name.regexpMatch("Find(All|Last)?") ) } private predicate propertyFlow(Property p) { - this.(RefType).getABaseType*() = p.getDeclaringType() - and + this.(RefType).getABaseType*() = p.getDeclaringType() and p.hasName("Values") } } /** Data flow for `System.Convert`. */ class SystemConvertFlow extends LibraryTypeDataFlow, SystemConvertClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { methodFlow(source, sink, c) and preservesValue = false } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { m = getAMethod() and source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() @@ -1144,34 +1220,37 @@ class SystemConvertFlow extends LibraryTypeDataFlow, SystemConvertClass { * (a tainted data contract object implies tainted data members). */ class DataContractFlow extends LibraryTypeDataFlow, DataContractClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = false } private predicate propertyFlow(Property p) { - p.getDeclaringType() = this - and + p.getDeclaringType() = this and p.getAnAttribute() instanceof DataMemberAttribute } } /** Data flow for `System.Web.HttpCookie`. */ class SystemWebHttpCookieFlow extends LibraryTypeDataFlow, SystemWebHttpCookie { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = false } @@ -1183,32 +1262,34 @@ class SystemWebHttpCookieFlow extends LibraryTypeDataFlow, SystemWebHttpCookie { /** Data flow for `System.Net.Cookie`. */ class SystemNetCookieFlow extends LibraryTypeDataFlow, SystemNetCookieClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = false } - private predicate propertyFlow(Property p) { - p = this.getValueProperty() - } + private predicate propertyFlow(Property p) { p = this.getValueProperty() } } /** Data flow for `System.Net.IPHostEntry`. */ class SystemNetIPHostEntryFlow extends LibraryTypeDataFlow, SystemNetIPHostEntryClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = false } @@ -1219,21 +1300,22 @@ class SystemNetIPHostEntryFlow extends LibraryTypeDataFlow, SystemNetIPHostEntry } /** Data flow for `System.Web.UI.WebControls.TextBox`. */ -class SystemWebUIWebControlsTextBoxFlow extends LibraryTypeDataFlow, SystemWebUIWebControlsTextBoxClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { +class SystemWebUIWebControlsTextBoxFlow extends LibraryTypeDataFlow, + SystemWebUIWebControlsTextBoxClass { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = false } - private predicate propertyFlow(Property p) { - p = getTextProperty() - } + private predicate propertyFlow(Property p) { p = getTextProperty() } } /** @@ -1246,7 +1328,10 @@ class SystemCollectionsGenericKeyValuePairStructFlow extends LibraryTypeDataFlow this instanceof SystemCollectionsGenericKeyValuePairStruct } - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or @@ -1256,16 +1341,13 @@ class SystemCollectionsGenericKeyValuePairStructFlow extends LibraryTypeDataFlow sink = TCallableFlowSinkReturn() and c = p.getGetter() ) - ) - and + ) and preservesValue = true } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c.getDeclaringType() = this - and - source = TCallableFlowSourceArg(c, 1) - and + c.getDeclaringType() = this and + source = TCallableFlowSourceArg(c, 1) and sink = TCallableFlowSinkReturn() } @@ -1280,14 +1362,16 @@ class SystemCollectionsGenericIEnumeratorInterfaceFlow extends LibraryTypeDataFl this instanceof SystemCollectionsGenericIEnumeratorInterface } - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = true } @@ -1297,38 +1381,42 @@ class SystemCollectionsGenericIEnumeratorInterfaceFlow extends LibraryTypeDataFl } /** Data flow for `System.Collections.IEnumerator`. */ -class SystemCollectionsIEnumeratorInterfaceFlow extends LibraryTypeDataFlow, SystemCollectionsIEnumeratorInterface { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { +class SystemCollectionsIEnumeratorInterfaceFlow extends LibraryTypeDataFlow, + SystemCollectionsIEnumeratorInterface { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { exists(Property p | propertyFlow(p) and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and c = p.getGetter() - ) - and + ) and preservesValue = true } - private predicate propertyFlow(Property p) { - p = getCurrentProperty() - } + private predicate propertyFlow(Property p) { p = getCurrentProperty() } } /** Data flow for `System.Threading.Tasks.Task`. */ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingTasksTaskClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or methodFlow(source, sink, c) - ) - and + ) and preservesValue = true } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { // flow from supplied state to supplied delegate - c.getDeclaringType() = this and exists(ConstructedDelegateType action | + c.getDeclaringType() = this and + exists(ConstructedDelegateType action | c.getParameter(1).getType() instanceof ObjectType and c.getParameter(0).getType() = action and action.getUnboundGeneric().(SystemActionTDelegateType).getNumberOfTypeParameters() = 1 and @@ -1338,11 +1426,13 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT ) } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m.getDeclaringType() = this - and + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m.getDeclaringType() = this and ( - m.hasName("ContinueWith") and ( + m.hasName("ContinueWith") and + ( // flow from supplied state to supplied delegate exists(ConstructedDelegateType delegate, int i, int j, int k | m.getParameter(i).getType() instanceof ObjectType and @@ -1365,19 +1455,22 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT ) ) or - m.hasName("FromResult") and ( + m.hasName("FromResult") and + ( source = TCallableFlowSourceArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - m.hasName("Run") and ( + m.hasName("Run") and + ( m.getReturnType() = any(SystemThreadingTasksTaskTClass c).getAConstructedGeneric() and m.(UnboundGenericMethod).getNumberOfTypeParameters() = 1 and source = TCallableFlowSourceDelegateArg(m, 0) and sink = TCallableFlowSinkReturn() ) or - m.getName().regexpMatch("WhenAll|WhenAny") and ( + m.getName().regexpMatch("WhenAll|WhenAny") and + ( m.getReturnType() = any(SystemThreadingTasksTaskTClass c).getAConstructedGeneric() and m.(UnboundGenericMethod).getNumberOfTypeParameters() = 1 and source = TCallableFlowSourceArg(m, _) and @@ -1389,11 +1482,12 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT /** Data flow for `System.Threading.Tasks.Task<>`. */ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { - SystemThreadingTasksTaskTFlow() { - this instanceof SystemThreadingTasksTaskTClass - } + SystemThreadingTasksTaskTFlow() { this instanceof SystemThreadingTasksTaskTClass } - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or @@ -1405,21 +1499,22 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() and c = p.getGetter() ) - ) - and + ) and preservesValue = true } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { // flow from supplied function into constructed Task - c.getDeclaringType() = this and ( + c.getDeclaringType() = this and + ( c.getParameter(0).getType() = any(SystemFuncDelegateType t).getAConstructedGeneric() and source = TCallableFlowSourceDelegateArg(c, 0) and sink = TCallableFlowSinkReturn() ) or // flow from supplied state to supplied delegate - c.getDeclaringType() = this and exists(ConstructedDelegateType func | + c.getDeclaringType() = this and + exists(ConstructedDelegateType func | c.getParameter(1).getType() instanceof ObjectType and c.getParameter(0).getType() = func and func.getUnboundGeneric().(SystemFuncDelegateType).getNumberOfTypeParameters() = 2 and @@ -1429,16 +1524,19 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { ) } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { m.getDeclaringType() = this and - m.hasName("ContinueWith") and ( + m.hasName("ContinueWith") and + ( exists(ConstructedDelegateType delegate, int i, int j | m.getParameter(i).getType() = delegate and ( delegate.getUnboundGeneric() instanceof SystemActionTDelegateType or delegate.getUnboundGeneric() instanceof SystemFuncDelegateType ) - | + | // flow from supplied state to supplied delegate exists(int k | delegate.getTypeArgument(j) instanceof ObjectType and @@ -1471,21 +1569,25 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow { /** Data flow for `System.Threading.Tasks.TaskFactory`(``). */ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { SystemThreadingTasksFactoryFlow() { - this instanceof SystemThreadingTasksClass - and + this instanceof SystemThreadingTasksClass and getName().regexpMatch("TaskFactory(<>)?") } - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { methodFlow(source, sink, c) and preservesValue = true } - private predicate methodFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m) { - m.getDeclaringType() = this - and + private predicate methodFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m + ) { + m.getDeclaringType() = this and ( - m.getName().regexpMatch("ContinueWhen(All|Any)") and ( + m.getName().regexpMatch("ContinueWhen(All|Any)") and + ( // flow into supplied function exists(ConstructedDelegateType delegate, ArrayType at, int i, int j, int k | at = m.getParameter(i).getType() and @@ -1509,7 +1611,8 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { ) ) or - m.hasName("StartNew") and ( + m.hasName("StartNew") and + ( // flow from supplied state to supplied delegate exists(ConstructedDelegateType delegate, int i, int j, int k | m.getParameter(i).getType() instanceof ObjectType and @@ -1537,7 +1640,10 @@ class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow { /** Data flow for `System.Text.Encoding`. */ library class SystemTextEncodingFlow extends LibraryTypeDataFlow, SystemTextEncodingClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { (c = getGetBytesMethod() or c = getGetStringMethod() or c = getGetCharsMethod()) and source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() and @@ -1547,134 +1653,126 @@ library class SystemTextEncodingFlow extends LibraryTypeDataFlow, SystemTextEnco /** Data flow for `System.IO.MemoryStream`. */ library class SystemIOMemoryStreamFlow extends LibraryTypeDataFlow, SystemIOMemoryStreamClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( constructorFlow(source, sink, c) or - ( - c = getToArrayMethod().getAnOverrider*() - and - source = TCallableFlowSourceQualifier() - and - sink = TCallableFlowSinkReturn() - ) - ) - and + c = getToArrayMethod().getAnOverrider*() and + source = TCallableFlowSourceQualifier() and + sink = TCallableFlowSinkReturn() + ) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() - and - c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType - and - source = TCallableFlowSourceArg(c, 0) - and + c = getAMember() and + c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and + source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() } } /** Data flow for `System.IO.Stream`. */ class SystemIOStreamFlow extends LibraryTypeDataFlow, SystemIOStreamClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( - ( - c = getAReadMethod().getAnOverrider*() - and - c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType - and - sink = TCallableFlowSinkArg(c, 0) - and - source = TCallableFlowSourceQualifier() - ) or ( - c = getAWriteMethod().getAnOverrider*() - and - c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType - and - source = TCallableFlowSourceArg(c, 0) - and - sink = TCallableFlowSinkQualifier() - ) or ( - c = any(Method m | m = getAMethod() and m.getName().matches("CopyTo%")).getAnOverrider*() - and - c.getParameter(0).getType() instanceof SystemIOStreamClass - and - source = TCallableFlowSourceQualifier() - and - sink = TCallableFlowSinkArg(c, 0) - ) - ) - and + c = getAReadMethod().getAnOverrider*() and + c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and + sink = TCallableFlowSinkArg(c, 0) and + source = TCallableFlowSourceQualifier() + or + c = getAWriteMethod().getAnOverrider*() and + c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and + source = TCallableFlowSourceArg(c, 0) and + sink = TCallableFlowSinkQualifier() + or + c = any(Method m | m = getAMethod() and m.getName().matches("CopyTo%")).getAnOverrider*() and + c.getParameter(0).getType() instanceof SystemIOStreamClass and + source = TCallableFlowSourceQualifier() and + sink = TCallableFlowSinkArg(c, 0) + ) and preservesValue = false } } /** Data flow for `System.IO.Compression.DeflateStream`. */ -class SystemIOCompressionDeflateStreamFlow extends LibraryTypeDataFlow, SystemIOCompressionDeflateStream { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { +class SystemIOCompressionDeflateStreamFlow extends LibraryTypeDataFlow, + SystemIOCompressionDeflateStream { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { constructorFlow(source, sink, c) and preservesValue = false } private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) { - c = getAMember() - and - source = TCallableFlowSourceArg(c, 0) - and + c = getAMember() and + source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() } } /** Data flow for `System.Xml.XmlReader`. */ class SystemXmlXmlReaderFlow extends LibraryTypeDataFlow, SystemXmlXmlReaderClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { - c = getCreateMethod() - and - source = TCallableFlowSourceArg(c, 0) - and - sink = TCallableFlowSinkReturn() - and + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { + c = getCreateMethod() and + source = TCallableFlowSourceArg(c, 0) and + sink = TCallableFlowSinkReturn() and preservesValue = false } } /** Data flow for `System.Xml.XmlDocument`. */ class SystemXmlXmlDocumentFlow extends LibraryTypeDataFlow, SystemXmlXmlDocumentClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { - c = getLoadMethod() - and - source = TCallableFlowSourceArg(c, 0) - and - sink = TCallableFlowSinkQualifier() - and + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { + c = getLoadMethod() and + source = TCallableFlowSourceArg(c, 0) and + sink = TCallableFlowSinkQualifier() and preservesValue = false } } /** Data flow for `System.Xml.XmlNode`. */ class SystemXmlXmlNodeFlow extends LibraryTypeDataFlow, SystemXmlXmlNodeClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( exists(Property p | p = getAProperty() and c = p.getGetter() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() - ) or - ( - c = getASelectNodeMethod() and - source = TCallableFlowSourceQualifier() and - sink = TCallableFlowSinkReturn() ) - ) - and + or + c = getASelectNodeMethod() and + source = TCallableFlowSourceQualifier() and + sink = TCallableFlowSinkReturn() + ) and preservesValue = false } } /** Data flow for `System.Xml.XmlNamedNodeMap`. */ class SystemXmlXmlNamedNodeMapFlow extends LibraryTypeDataFlow, SystemXmlXmlNamedNodeMapClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { c = getGetNamedItemMethod() and source = TCallableFlowSourceQualifier() and sink = TCallableFlowSinkReturn() and @@ -1684,13 +1782,15 @@ class SystemXmlXmlNamedNodeMapFlow extends LibraryTypeDataFlow, SystemXmlXmlName /** Data flow for `System.IO.Path`. */ class SystemIOPathFlow extends LibraryTypeDataFlow, SystemIOPathClass { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { - ( - c = getAMethod("Combine") and - source = TCallableFlowSourceArg(c, _) and - sink = TCallableFlowSinkReturn() and - preservesValue = false - ) or + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { + c = getAMethod("Combine") and + source = TCallableFlowSourceArg(c, _) and + sink = TCallableFlowSinkReturn() and + preservesValue = false + or exists(Parameter p | c = getAMethod() and c.getName().matches("Get%") and @@ -1705,14 +1805,16 @@ class SystemIOPathFlow extends LibraryTypeDataFlow, SystemIOPathClass { /** Data flow for `System.Web.HttpUtility`. */ class SystemWebHttpUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpUtility { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( c = getAnHtmlAttributeEncodeMethod() or c = getAnHtmlEncodeMethod() or c = getAJavaScriptStringEncodeMethod() or c = getAnUrlEncodeMethod() - ) - and + ) and source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() and preservesValue = false @@ -1721,12 +1823,14 @@ class SystemWebHttpUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpUtility /** Data flow for `System.Web.HttpServerUtility`. */ class SystemWebHttpServerUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpServerUtility { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( c = getAnHtmlEncodeMethod() or c = getAnUrlEncodeMethod() - ) - and + ) and source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() and preservesValue = false @@ -1735,12 +1839,14 @@ class SystemWebHttpServerUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpS /** Data flow for `System.Net.WebUtility`. */ class SystemNetWebUtilityFlow extends LibraryTypeDataFlow, SystemNetWebUtility { - override predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, boolean preservesValue) { + override predicate callableFlow( + CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c, + boolean preservesValue + ) { ( c = getAnHtmlEncodeMethod() or c = getAnUrlEncodeMethod() - ) - and + ) and source = TCallableFlowSourceArg(c, 0) and sink = TCallableFlowSinkReturn() and preservesValue = false diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll index e0daa03f5fd..eee39b11f43 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/Nullness.qll @@ -50,9 +50,9 @@ class AlwaysNullExpr extends Expr { this instanceof NullLiteral or this = any(ConditionalExpr ce | - ce.getThen() instanceof AlwaysNullExpr and - ce.getElse() instanceof AlwaysNullExpr - ) + ce.getThen() instanceof AlwaysNullExpr and + ce.getElse() instanceof AlwaysNullExpr + ) or this.(AssignExpr).getRValue() instanceof AlwaysNullExpr or @@ -65,9 +65,7 @@ class NonNullExpr extends Expr { NonNullExpr() { G::Internal::nonNullValue(this) or - exists(NonNullExpr mid | - G::Internal::nonNullValueImplied(mid, this) - ) + exists(NonNullExpr mid | G::Internal::nonNullValueImplied(mid, this)) or this instanceof G::NullGuardedExpr or @@ -79,17 +77,16 @@ class NonNullExpr extends Expr { private predicate nonNullDef(Ssa::Definition v) { v.(Ssa::ExplicitDefinition).getADefinition().getSource() instanceof NonNullExpr or - exists(AssignableDefinition ad | - ad = v.(Ssa::ExplicitDefinition).getADefinition() | + exists(AssignableDefinition ad | ad = v.(Ssa::ExplicitDefinition).getADefinition() | ad instanceof AssignableDefinitions::IsPatternDefinition or ad instanceof AssignableDefinitions::TypeCasePatternDefinition or ad = any(AssignableDefinitions::LocalVariableDefinition d | - d.getExpr() = any(SpecificCatchClause scc).getVariableDeclExpr() - or - d.getExpr() = any(ForeachStmt fs).getAVariableDeclExpr() - ) + d.getExpr() = any(SpecificCatchClause scc).getVariableDeclExpr() + or + d.getExpr() = any(ForeachStmt fs).getAVariableDeclExpr() + ) ) } @@ -105,9 +102,10 @@ private predicate dereferenceAt(BasicBlock bb, int i, Ssa::Definition def, Deref * Holds if `e` having abstract value `vExpr` implies that SSA definition `def` * has abstract value `vDef`. */ -private predicate exprImpliesSsaDef(Expr e, G::AbstractValue vExpr, Ssa::Definition def, G::AbstractValue vDef) { - exists(G::Internal::Guard g | - G::Internal::impliesSteps(e, vExpr, g, vDef) | +private predicate exprImpliesSsaDef( + Expr e, G::AbstractValue vExpr, Ssa::Definition def, G::AbstractValue vDef +) { + exists(G::Internal::Guard g | G::Internal::impliesSteps(e, vExpr, g, vDef) | g = def.getARead() or g = def.(Ssa::ExplicitDefinition).getADefinition().getTargetAccess() @@ -120,7 +118,8 @@ private predicate exprImpliesSsaDef(Expr e, G::AbstractValue vExpr, Ssa::Definit */ private predicate ensureNotNullAt(BasicBlock bb, int i, Ssa::Definition def) { exists(Expr e, G::AbstractValue v, NullValue nv | - G::Internal::asserts(bb.getNode(i).getElement(), e, v) | + G::Internal::asserts(bb.getNode(i).getElement(), e, v) + | exprImpliesSsaDef(e, v, def, nv) and not nv.isNull() ) @@ -130,7 +129,9 @@ private predicate ensureNotNullAt(BasicBlock bb, int i, Ssa::Definition def) { * Holds if the `i`th node of basic block `bb` is a dereference `d` of SSA * definition `def`, and `def` may potentially be `null`. */ -private predicate potentialNullDereferenceAt(BasicBlock bb, int i, Ssa::Definition def, Dereference d) { +private predicate potentialNullDereferenceAt( + BasicBlock bb, int i, Ssa::Definition def, Dereference d +) { dereferenceAt(bb, i, def, d) and not exists(int j | ensureNotNullAt(bb, j, def) | j < i) } @@ -142,16 +143,16 @@ private predicate potentialNullDereferenceAt(BasicBlock bb, int i, Ssa::Definiti * If the returned element takes the `s` branch, then `def` is guaranteed to be * `null` if `nv.isNull()` holds, and non-`null` otherwise. */ -private ControlFlowElement getANullCheck(Ssa::Definition def, SuccessorTypes::ConditionalSuccessor s, NullValue nv) { - exists(Expr e, G::AbstractValue v | - v.branch(result, s, e) | - exprImpliesSsaDef(e, v, def, nv) - ) +private ControlFlowElement getANullCheck( + Ssa::Definition def, SuccessorTypes::ConditionalSuccessor s, NullValue nv +) { + exists(Expr e, G::AbstractValue v | v.branch(result, s, e) | exprImpliesSsaDef(e, v, def, nv)) } private predicate isMaybeNullArgument(Ssa::ExplicitDefinition def, MaybeNullExpr arg) { exists(AssignableDefinitions::ImplicitParameterDefinition pdef, Parameter p | - pdef = def.getADefinition() | + pdef = def.getADefinition() + | p = pdef.getParameter().getSourceDeclaration() and p.getAnAssignedArgument() = arg and not arg.getEnclosingCallable().getEnclosingCallable*() instanceof TestMethod @@ -161,14 +162,11 @@ private predicate isMaybeNullArgument(Ssa::ExplicitDefinition def, MaybeNullExpr /** Holds if `def` is an SSA definition that may be `null`. */ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason) { // A variable compared to `null` might be `null` - exists(G::DereferenceableExpr de | - de = def.getARead() | + exists(G::DereferenceableExpr de | de = def.getARead() | reason = de.getANullCheck(_, true) and msg = "as suggested by $@ null check" and not de = any(Ssa::PseudoDefinition pdef).getARead() and - strictcount(Element e | - e = any(Ssa::Definition def0 | de = def0.getARead()).getElement() - ) = 1 and + strictcount(Element e | e = any(Ssa::Definition def0 | de = def0.getARead()).getElement()) = 1 and not nonNullDef(def) and // Don't use a check as reason if there is a `null` assignment // or argument @@ -181,16 +179,14 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason) msg = "because of $@ null argument" or // If the source of a variable is `null` then the variable may be `null` - exists(AssignableDefinition adef | - adef = def.(Ssa::ExplicitDefinition).getADefinition() | + exists(AssignableDefinition adef | adef = def.(Ssa::ExplicitDefinition).getADefinition() | adef.getSource() instanceof MaybeNullExpr and reason = adef.getExpr() and msg = "because of $@ assignment" ) or // A variable of nullable type may be null - exists(Dereference d | - dereferenceAt(_, _, def, d) | + exists(Dereference d | dereferenceAt(_, _, def, d) | d.hasNullableType() and not def instanceof Ssa::PseudoDefinition and reason = def.getSourceVariable().getAssignable() and @@ -203,7 +199,9 @@ private predicate defMaybeNull(Ssa::Definition def, string msg, Element reason) * be `null` in basic block `bb2`. The SSA definitions share the same source * variable. */ -private predicate defNullImpliesStep(Ssa::Definition def1, BasicBlock bb1, Ssa::Definition def2, BasicBlock bb2) { +private predicate defNullImpliesStep( + Ssa::Definition def1, BasicBlock bb1, Ssa::Definition def2, BasicBlock bb2 +) { exists(Ssa::SourceVariable v | defMaybeNull(v.getAnSsaDefinition(), _, _) and def1.getSourceVariable() = v @@ -221,7 +219,8 @@ private predicate defNullImpliesStep(Ssa::Definition def1, BasicBlock bb1, Ssa:: not ensureNotNullAt(bb1, _, def1) and bb2 = bb1.getASuccessor() and not exists(SuccessorTypes::ConditionalSuccessor s, NullValue nv | - bb1.getLastNode() = getANullCheck(def1, s, nv).getAControlFlowNode() | + bb1.getLastNode() = getANullCheck(def1, s, nv).getAControlFlowNode() + | bb2 = bb1.getASuccessorByType(s) and not nv.isNull() ) @@ -235,8 +234,7 @@ private predicate defMaybeNullInBlock(Ssa::Definition def, BasicBlock bb) { defMaybeNull(def, _, _) and bb = def.getBasicBlock() or - exists(BasicBlock mid, Ssa::Definition midDef | - defMaybeNullInBlock(midDef, mid) | + exists(BasicBlock mid, Ssa::Definition midDef | defMaybeNullInBlock(midDef, mid) | defNullImpliesStep(midDef, mid, def, bb) ) } @@ -246,8 +244,7 @@ private predicate defMaybeNullInBlock(Ssa::Definition def, BasicBlock bb) { * dereference. */ private predicate nullDerefCandidateVariable(Ssa::SourceVariable v) { - exists(Ssa::Definition def, BasicBlock bb | - potentialNullDereferenceAt(bb, _, def, _) | + exists(Ssa::Definition def, BasicBlock bb | potentialNullDereferenceAt(bb, _, def, _) | defMaybeNullInBlock(def, bb) and v = def.getSourceVariable() ) @@ -272,14 +269,12 @@ private newtype TPathNode = nullDerefCandidateVariable(def.getSourceVariable()) and defMaybeNull(def, msg, reason) and if isMaybeNullArgument(def, reason) then isNullArgument = true else isNullArgument = false - } - or + } or TInternalPathNode(Ssa::Definition def, BasicBlock bb) { succStep(_, def, bb) or succNullArgument(_, def, bb) - } - or + } or TSinkPathNode(Ssa::Definition def, BasicBlock bb, int i, Dereference d) { potentialNullDereferenceAt(bb, i, def, d) and ( @@ -314,8 +309,11 @@ abstract class PathNode extends TPathNode { private class SourcePathNode extends PathNode, TSourcePathNode { private Ssa::Definition def; + private string msg; + private Element reason; + private boolean isNullArgument; SourcePathNode() { this = TSourcePathNode(def, msg, reason, isNullArgument) } @@ -341,22 +339,17 @@ private class SourcePathNode extends PathNode, TSourcePathNode { } override string toString() { - if isNullArgument = true then - result = reason.toString() - else - result = def.toString() + if isNullArgument = true then result = reason.toString() else result = def.toString() } override Location getLocation() { - if isNullArgument = true then - result = reason.getLocation() - else - result = def.getLocation() + if isNullArgument = true then result = reason.getLocation() else result = def.getLocation() } } private class InternalPathNode extends PathNode, TInternalPathNode { private Ssa::Definition def; + private BasicBlock bb; InternalPathNode() { this = TInternalPathNode(def, bb) } @@ -376,8 +369,11 @@ private class InternalPathNode extends PathNode, TInternalPathNode { private class SinkPathNode extends PathNode, TSinkPathNode { private Ssa::Definition def; + private BasicBlock bb; + private int i; + private Dereference d; SinkPathNode() { this = TSinkPathNode(def, bb, i, d) } @@ -400,10 +396,8 @@ private class SinkPathNode extends PathNode, TSinkPathNode { * for `Dereference::is[First]MaybeNull()`. */ module PathGraph { - query predicate nodes(PathNode n) { - n.getASuccessor*() instanceof SinkPathNode - } - + query predicate nodes(PathNode n) { n.getASuccessor*() instanceof SinkPathNode } + query predicate edges(PathNode pred, PathNode succ) { nodes(pred) and nodes(succ) and @@ -431,12 +425,13 @@ private predicate defReaches(Ssa::Definition def, ControlFlow::Node cfn, boolean exists(def.getAFirstReadAtNode(cfn)) and (always = true or always = false) or - exists(ControlFlow::Node mid | - defReaches(def, mid, always) | + exists(ControlFlow::Node mid | defReaches(def, mid, always) | Ssa::Internal::adjacentReadPairSameVar(mid, cfn) and not mid = any(Dereference d | - if always = true then d.isAlwaysNull(def.getSourceVariable()) else d.isMaybeNull(def, _, _, _, _) - ).getAControlFlowNode() + if always = true + then d.isAlwaysNull(def.getSourceVariable()) + else d.isMaybeNull(def, _, _, _, _) + ).getAControlFlowNode() ) } @@ -446,20 +441,21 @@ private predicate defReaches(Ssa::Definition def, ControlFlow::Node cfn, boolean */ class Dereference extends G::DereferenceableExpr { Dereference() { - if this.hasNullableType() then ( + if this.hasNullableType() + then ( // Strictly speaking, these throw `InvalidOperationException`s and not // `NullReferenceException`s this = any(PropertyAccess pa | pa.getTarget().hasName("Value")).getQualifier() or exists(Type underlyingType | - this = any(CastExpr ce | ce.getTargetType() = underlyingType).getExpr() | + this = any(CastExpr ce | ce.getTargetType() = underlyingType).getExpr() + | underlyingType = this.getType().(NullableType).getUnderlyingType() or underlyingType = this.getType() and not underlyingType instanceof NullableType ) - ) - else ( + ) else ( this = any(QualifiableExpr qe | not qe.isConditional()).getQualifier() and not this instanceof ThisAccess and not this instanceof BaseAccess and @@ -472,11 +468,15 @@ class Dereference extends G::DereferenceableExpr { exists(ExtensionMethodCall emc, Parameter p | this = emc.getArgumentForParameter(p) and p.hasExtensionMethodModifier() and - not emc.isConditional() | + not emc.isConditional() + | p.fromSource() // assume all non-source extension methods perform a dereference implies - exists(Ssa::ExplicitDefinition def, AssignableDefinitions::ImplicitParameterDefinition pdef | - pdef = def.getADefinition() | + exists( + Ssa::ExplicitDefinition def, AssignableDefinitions::ImplicitParameterDefinition pdef + | + pdef = def.getADefinition() + | p.getSourceDeclaration() = pdef.getParameter() and def.getARead() instanceof Dereference ) @@ -485,8 +485,7 @@ class Dereference extends G::DereferenceableExpr { } private predicate isAlwaysNull0(Ssa::Definition def) { - forall(Ssa::Definition input | - input = getAnUltimateDefinition(def) | + forall(Ssa::Definition input | input = getAnUltimateDefinition(def) | input.(Ssa::ExplicitDefinition).getADefinition().getSource() instanceof AlwaysNullExpr ) and not nonNullDef(def) and @@ -503,15 +502,12 @@ class Dereference extends G::DereferenceableExpr { // Exclude fields, properties, and captured variables, as they may not have an // accurate SSA representation v.getAssignable() = any(LocalScopeVariable lsv | - strictcount(Callable c | - c = any(AssignableDefinition ad | ad.getTarget() = lsv).getEnclosingCallable() - ) = 1 - ) and + strictcount(Callable c | + c = any(AssignableDefinition ad | ad.getTarget() = lsv).getEnclosingCallable() + ) = 1 + ) and ( - forex(Ssa::Definition def0 | - this = def0.getARead() | - this.isAlwaysNull0(def0) - ) + forex(Ssa::Definition def0 | this = def0.getARead() | this.isAlwaysNull0(def0)) or exists(NullValue nv | this.(G::GuardedExpr).mustHaveValue(nv) and @@ -535,7 +531,9 @@ class Dereference extends G::DereferenceableExpr { * Holds if this expression dereferences SSA definition `def`, which may * be `null`. */ - predicate isMaybeNull(Ssa::Definition def, SourcePathNode source, SinkPathNode sink, string msg, Element reason) { + predicate isMaybeNull( + Ssa::Definition def, SourcePathNode source, SinkPathNode sink, string msg, Element reason + ) { source.getASuccessor*() = sink and msg = source.getMessage() and reason = source.getReason() and @@ -549,7 +547,9 @@ class Dereference extends G::DereferenceableExpr { * be `null`, and this expression can be reached from `def` without passing * through another such dereference. */ - predicate isFirstMaybeNull(Ssa::Definition def, SourcePathNode source, SinkPathNode sink, string msg, Element reason) { + predicate isFirstMaybeNull( + Ssa::Definition def, SourcePathNode source, SinkPathNode sink, string msg, Element reason + ) { this.isMaybeNull(def, source, sink, msg, reason) and defReaches(def, this.getAControlFlowNode(), false) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll index ac0049037fc..91dbdfd4cb1 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/SSA.qll @@ -20,54 +20,47 @@ module Ssa { } /** An instance field or property. */ - class InstanceFieldOrProp extends FieldOrProp { - InstanceFieldOrProp() { - not this.isStatic() - } - } + class InstanceFieldOrProp extends FieldOrProp { InstanceFieldOrProp() { not this.isStatic() } } /** An access to a field or a property. */ class FieldOrPropAccess extends AssignableAccess, QualifiableExpr { - FieldOrPropAccess() { - this.getTarget() instanceof FieldOrProp - } + FieldOrPropAccess() { this.getTarget() instanceof FieldOrProp } } /** An access to a field or a property that reads the underlying value. */ class FieldOrPropRead extends FieldOrPropAccess, AssignableRead { } - private cached module Cached { - cached newtype TSourceVariable = + cached + private module Cached { + cached + newtype TSourceVariable = TLocalVar(Callable c, LocalScopeVariable v) { - c = v.getCallable() or + c = v.getCallable() + or // Local scope variables can be captured c = v.getAnAccess().getEnclosingCallable() - } - or + } or TPlainFieldOrProp(Callable c, FieldOrProp f) { exists(FieldOrPropRead fr | isPlainFieldOrPropAccess(fr, f, c)) - } - or + } or TQualifiedFieldOrProp(Callable c, SourceVariable q, InstanceFieldOrProp f) { exists(FieldOrPropRead fr | isQualifiedFieldOrPropAccess(fr, f, c, q)) } /** Gets an access to source variable `v`. */ - cached AssignableAccess getAnAccess(SourceVariable v) { + cached + AssignableAccess getAnAccess(SourceVariable v) { exists(Callable c | - exists(LocalScopeVariable lsv | - v = TLocalVar(c, lsv) | + exists(LocalScopeVariable lsv | v = TLocalVar(c, lsv) | result = lsv.getAnAccess() and result.getEnclosingCallable() = c ) or - exists(FieldOrProp fp | - v = TPlainFieldOrProp(c, fp) | + exists(FieldOrProp fp | v = TPlainFieldOrProp(c, fp) | isPlainFieldOrPropAccess(result, fp, c) ) or - exists(FieldOrProp fp, SourceVariable q | - v = TQualifiedFieldOrProp(c, q, fp) | + exists(FieldOrProp fp, SourceVariable q | v = TQualifiedFieldOrProp(c, q, fp) | isQualifiedFieldOrPropAccess(result, fp, c, q) ) ) @@ -88,7 +81,9 @@ module Ssa { * Holds if `fpa` is an access inside callable `c` of instance field or property * `fp` with qualifier `q`. */ - predicate isQualifiedFieldOrPropAccess(FieldOrPropAccess fpa, InstanceFieldOrProp fp, Callable c, SourceVariable q) { + predicate isQualifiedFieldOrPropAccess( + FieldOrPropAccess fpa, InstanceFieldOrProp fp, Callable c, SourceVariable q + ) { fieldOrPropAccessInCallable(fpa, fp, c) and fpa.getQualifier() = q.getAnAccess() } @@ -113,18 +108,14 @@ module Ssa { * targeting source variable `v`. */ predicate variableDefinition(BasicBlock bb, int i, SourceVariable v, AssignableDefinition ad) { - ad = v.getADefinition() - and - ad.getAControlFlowNode() = bb.getNode(i) - and + ad = v.getADefinition() and + ad.getAControlFlowNode() = bb.getNode(i) and // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` - not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | - first = ad | + not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = ad | second.getAssignment() = first.getAssignment() and second.getEvaluationOrder() > first.getEvaluationOrder() and second = v.getADefinition() - ) - and + ) and // In cases like `M(out x, out x)`, there is no inherent evaluation order, so we // collapse the two definitions of `x`, using the first access as the representative, // and expose both definitions in `ExplicitDefinition.getADefinition()` @@ -147,12 +138,12 @@ module Ssa { * variable `v`. The Boolean `certain` indicates whether the write is certain. */ private predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { - exists(AssignableDefinition ad | - variableDefinition(bb, i, v, ad) | - if any(AssignableDefinition ad0 | ad0 = ad or ad0 = getASameOutRefDefAfter(v, ad)).isCertain() then - certain = true - else - certain = false + exists(AssignableDefinition ad | variableDefinition(bb, i, v, ad) | + if + any(AssignableDefinition ad0 | ad0 = ad or ad0 = getASameOutRefDefAfter(v, ad)) + .isCertain() + then certain = true + else certain = false ) or variableWrite(bb, i, v.(QualifiedFieldOrPropSourceVariable).getQualifier(), certain) @@ -163,8 +154,7 @@ module Ssa { */ newtype ReadKind = /** An actual read. */ - ActualRead() - or + ActualRead() or /** * A pseudo read for a `ref` or `out` variable at the end of the variable's enclosing * callable. A pseudo read is inserted to make assignments to `out`/`ref` variables @@ -176,15 +166,13 @@ module Ssa { * } * ``` */ - OutRefExitRead() - or + OutRefExitRead() or /** * A pseudo read for a captured variable at the end of the capturing * callable. A write to a captured variable needs to be live for the same reasons * as a write to a `ref` or `out` variable (see above). */ - CapturedVarExitRead() - or + CapturedVarExitRead() or /** * A pseudo read for a `ref` variable, just prior to an update of the referenced value. * A pseudo read is inserted to make assignments to the `ref` variable live, for example @@ -206,7 +194,9 @@ module Ssa { * Holds if the `i`th node `node` of basic block `bb` reads source variable `v`. * The read at `node` is of kind `rk`. */ - predicate variableRead(BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk) { + predicate variableRead( + BasicBlock bb, int i, SourceVariable v, ControlFlow::Node node, ReadKind rk + ) { v.getAnAccess().(AssignableRead) = node.getElement() and node = bb.getNode(i) and rk = ActualRead() @@ -221,25 +211,33 @@ module Ssa { rk = RefReadBeforeWrite() } - private predicate outRefExitRead(ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::ExitNode node) { + private predicate outRefExitRead( + ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, + ControlFlow::Nodes::ExitNode node + ) { exists(LocalScopeVariable lsv | lsv = v.getAssignable() and ebb.getNode(i) = node and - node.getCallable() = lsv.getCallable() | + node.getCallable() = lsv.getCallable() + | lsv.isRef() or lsv.(Parameter).isOut() ) } - private predicate capturedVarExitRead(ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, ControlFlow::Nodes::ExitNode node) { - exists(BasicBlock bb | - variableDefinition(bb, _, v, _) | + private predicate capturedVarExitRead( + ControlFlow::BasicBlocks::ExitBlock ebb, int i, LocalScopeSourceVariable v, + ControlFlow::Nodes::ExitNode node + ) { + exists(BasicBlock bb | variableDefinition(bb, _, v, _) | ebb.getNode(i) = node and bb.getCallable() = ebb.getCallable() and bb.getCallable() != v.getAssignable().getCallable() ) } - private predicate refReadBeforeWrite(BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Node node) { + private predicate refReadBeforeWrite( + BasicBlock bb, int i, LocalScopeSourceVariable v, ControlFlow::Node node + ) { exists(AssignableDefinitions::AssignmentDefinition def, LocalVariable lv | def.getTarget() = lv and lv.isRef() and @@ -254,8 +252,7 @@ module Ssa { * (certain or uncertain) writes. */ newtype RefKind = - Read(ReadKind rk) - or + Read(ReadKind rk) or Write(boolean certain) { certain = true or certain = false } /** @@ -263,15 +260,9 @@ module Ssa { * (when `k` is `Read()`) or a write (when `k` is `UncertainWrite()` or `Write()`). */ predicate ref(BasicBlock bb, int i, SourceVariable v, RefKind k) { - exists(ReadKind rk | - variableRead(bb, i, v, _, rk) | - k = Read(rk) - ) + exists(ReadKind rk | variableRead(bb, i, v, _, rk) | k = Read(rk)) or - exists(boolean certain | - variableWrite(bb, i, v, certain) | - k = Write(certain) - ) + exists(boolean certain | variableWrite(bb, i, v, certain) | k = Write(certain)) } /** @@ -294,11 +285,11 @@ module Ssa { */ private int firstReadOrCertainWrite(BasicBlock bb, SourceVariable v) { result = min(int r, RefKind k | - r = refRank(bb, _, v, k) and - k != Write(false) + r = refRank(bb, _, v, k) and + k != Write(false) | - r - ) + r + ) } /** @@ -355,13 +346,9 @@ module Ssa { * `v` is of kind `rk`. */ predicate liveAfterWrite(BasicBlock bb, int i, SourceVariable v, ReadKind rk) { - exists (int rnk | - rnk = refRank(bb, i, v, Write(_)) | - liveAtRank(bb, i, v, rnk, rk) - ) + exists(int rnk | rnk = refRank(bb, i, v, Write(_)) | liveAtRank(bb, i, v, rnk, rk)) } } - private import SourceVariableImpl /** @@ -389,17 +376,15 @@ module Ssa { // Local variable declaration without initializer not exists(result.getTargetAccess()) and this = any(LocalScopeSourceVariable v | - result.getTarget() = v.getAssignable() and - result.getEnclosingCallable() = v.getEnclosingCallable() - ) + result.getTarget() = v.getAssignable() and + result.getEnclosingCallable() = v.getEnclosingCallable() + ) } /** * Holds if this variable is captured by a nested callable. */ - predicate isCaptured() { - this.getAssignable().(LocalScopeVariable).isCaptured() - } + predicate isCaptured() { this.getAssignable().(LocalScopeVariable).isCaptured() } /** Gets the callable in which this source variable is defined. */ Callable getEnclosingCallable() { none() } @@ -411,9 +396,7 @@ module Ssa { Location getLocation() { none() } /** Gets the type of this source variable. */ - Type getType() { - result = this.getAssignable().getType() - } + Type getType() { result = this.getAssignable().getType() } /** Gets the qualifier of this source variable, if any. */ SourceVariable getQualifier() { none() } @@ -422,39 +405,26 @@ module Ssa { * Gets an SSA definition that has this variable as its underlying * source variable. */ - deprecated - Definition getAnDefinition() { - result.getSourceVariable() = this - } + deprecated Definition getAnDefinition() { result.getSourceVariable() = this } /** * Gets an SSA definition that has this variable as its underlying * source variable. */ - Definition getAnSsaDefinition() { - result.getSourceVariable() = this - } + Definition getAnSsaDefinition() { result.getSourceVariable() = this } } /** Provides different types of `SourceVariable`s. */ module SourceVariables { /** A local scope variable. */ class LocalScopeSourceVariable extends SourceVariable, TLocalVar { - override LocalScopeVariable getAssignable() { - this = TLocalVar(_, result) - } + override LocalScopeVariable getAssignable() { this = TLocalVar(_, result) } - override Callable getEnclosingCallable() { - this = TLocalVar(result, _) - } + override Callable getEnclosingCallable() { this = TLocalVar(result, _) } - override string toString() { - result = getAssignable().getName() - } + override string toString() { result = getAssignable().getName() } - override Location getLocation() { - result = getAssignable().getLocation() - } + override Location getLocation() { result = getAssignable().getLocation() } } /** A fully qualified field or property. */ @@ -474,14 +444,13 @@ module Ssa { * code location. This is used as the representative location. */ private FieldOrPropAccess getFirstAccess() { - result = min(this.getAnAccess() as a order by - a.getLocation().getStartLine(), a.getLocation().getStartColumn() - ) + result = min(this.getAnAccess() as a + order by + a.getLocation().getStartLine(), a.getLocation().getStartColumn() + ) } - override Location getLocation() { - result = getFirstAccess().getLocation() - } + override Location getLocation() { result = getFirstAccess().getLocation() } /** * Holds if the this field or any of the fields part of the qualifier @@ -495,38 +464,28 @@ module Ssa { /** A plain field or property. */ class PlainFieldOrPropSourceVariable extends FieldOrPropSourceVariable, TPlainFieldOrProp { - override Callable getEnclosingCallable() { - this = TPlainFieldOrProp(result, _) - } + override Callable getEnclosingCallable() { this = TPlainFieldOrProp(result, _) } override string toString() { exists(FieldOrProp f, string prefix | f = getAssignable() and - result = prefix + "." + getAssignable() | - if f.isStatic() then - prefix = f.getDeclaringType().getQualifiedName() - else - prefix = "this" + result = prefix + "." + getAssignable() + | + if f.isStatic() then prefix = f.getDeclaringType().getQualifiedName() else prefix = "this" ) } } /** A qualified field or property. */ - class QualifiedFieldOrPropSourceVariable extends FieldOrPropSourceVariable, TQualifiedFieldOrProp { - override Callable getEnclosingCallable() { - this = TQualifiedFieldOrProp(result, _, _) - } + class QualifiedFieldOrPropSourceVariable extends FieldOrPropSourceVariable, + TQualifiedFieldOrProp { + override Callable getEnclosingCallable() { this = TQualifiedFieldOrProp(result, _, _) } - override SourceVariable getQualifier() { - this = TQualifiedFieldOrProp(_, result, _) - } + override SourceVariable getQualifier() { this = TQualifiedFieldOrProp(_, result, _) } - override string toString() { - result = getQualifier() + "." + getAssignable() - } + override string toString() { result = getQualifier() + "." + getAssignable() } } } - private import SourceVariables private module TrackedVariablesImpl { @@ -564,19 +523,15 @@ module Ssa { * non-overridable trivial property. */ predicate trackFieldOrProp(FieldOrPropSourceVariable fp) { - multiAccessed(fp) - and - not fp.isVolatile() - and - exists(Assignable a | - a = fp.getAssignable() | + multiAccessed(fp) and + not fp.isVolatile() and + exists(Assignable a | a = fp.getAssignable() | a instanceof Field or a = any(TrivialProperty p | not p.isOverridableOrImplementable()) ) } } - private import TrackedVariablesImpl /** @@ -599,9 +554,7 @@ module Ssa { * definition prior to every read. */ private class UntrackedVar extends SourceVariable { - UntrackedVar() { - not this instanceof TrackedVar - } + UntrackedVar() { not this instanceof TrackedVar } } private module SsaDefReaches { @@ -622,7 +575,9 @@ module Ssa { * A classification of SSA variable references into reads and non-trivial * SSA definitions. */ - private newtype SsaRefKind = SsaRead() or SsaDef() + private newtype SsaRefKind = + SsaRead() or + SsaDef() /** * Holds if the `i`th node of basic block `bb` is a reference to `v`, @@ -664,7 +619,9 @@ module Ssa { * Holds if the non-trivial SSA definition `def` reaches rank index `rankix` * in its own basic block `bb`. */ - private predicate ssaDefReachesRank(BasicBlock bb, TrackedDefinition def, int rankix, TrackedVar v) { + private predicate ssaDefReachesRank( + BasicBlock bb, TrackedDefinition def, int rankix, TrackedVar v + ) { exists(int i | rankix = ssaRefRank(bb, i, v, SsaDef()) and definesAt(def, bb, i, v) @@ -679,7 +636,9 @@ module Ssa { * same basic block without crossing another SSA definition of `v`. * The read at `node` is of kind `rk`. */ - private predicate ssaDefReachesReadWithinBlock(TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk) { + private predicate ssaDefReachesReadWithinBlock( + TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk + ) { exists(BasicBlock bb, int rankix, int i | ssaDefReachesRank(bb, def, rankix, v) and rankix = ssaRefRank(bb, i, v, SsaRead()) and @@ -692,7 +651,9 @@ module Ssa { * definition `redef` in the same basic block, without crossing another SSA * definition of `v`. */ - private predicate ssaDefReachesUncertainDefWithinBlock(TrackedVar v, TrackedDefinition def, UncertainDefinition redef) { + private predicate ssaDefReachesUncertainDefWithinBlock( + TrackedVar v, TrackedDefinition def, UncertainDefinition redef + ) { exists(BasicBlock bb, int rankix, int i | ssaDefReachesRank(bb, def, rankix, v) and rankix = ssaRefRank(bb, i, v, SsaDef()) - 1 and @@ -724,10 +685,9 @@ module Ssa { blockPrecedesVar(v, bb2) } - pragma [noinline] + pragma[noinline] private predicate varBlockReachesRec(TrackedVar v, BasicBlock bb1, BasicBlock bb2) { - exists(BasicBlock mid | - varBlockReaches(v, bb1, mid) | + exists(BasicBlock mid | varBlockReaches(v, bb1, mid) | bb2 = mid.getASuccessor() and not varOccursInBlock(v, mid) ) @@ -758,7 +718,8 @@ module Ssa { ssaRefRank(bb2, i2, v, _) = 1 } - private cached module Cached { + cached + private module Cached { /** * Holds if `cfn` is a last read of the non-trivial SSA definition `def`. * That is, `cfn` can reach the end of the enclosing callable, or another @@ -770,7 +731,8 @@ module Ssa { exists(TrackedVar v, BasicBlock bb, int i, int rnk | exists(def.getAReadAtNode(cfn)) and variableRead(bb, i, v, cfn, _) and - rnk = ssaRefRank(bb, i, v, SsaRead()) | + rnk = ssaRefRank(bb, i, v, SsaRead()) + | // Next reference to `v` inside `bb` is a write rnk + 1 = ssaRefRank(bb, _, v, SsaDef()) or @@ -781,8 +743,7 @@ module Ssa { not varBlockReaches(v, bb, _) or // Read reaches an SSA definition in a successor block - exists(BasicBlock bb2 | - varBlockReaches(v, bb, bb2) | + exists(BasicBlock bb2 | varBlockReaches(v, bb, bb2) | 1 = ssaRefRank(bb2, _, v, SsaDef()) ) ) @@ -790,16 +751,16 @@ module Ssa { } pragma[noinline] - private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, TrackedDefinition def, TrackedVar v) { - exists(BasicBlock idom | - ssaDefReachesEndOfBlock(idom, def, v) | - /* The construction of SSA form ensures that each read of a variable is - * dominated by its definition. An SSA definition therefore reaches a - * control flow node if it is the _closest_ SSA definition that dominates - * the node. If two definitions dominate a node then one must dominate the - * other, so therefore the definition of _closest_ is given by the dominator - * tree. Thus, reaching definitions can be calculated in terms of dominance. - */ + private predicate ssaDefReachesEndOfBlockRec( + BasicBlock bb, TrackedDefinition def, TrackedVar v + ) { + exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) | + // The construction of SSA form ensures that each read of a variable is + // dominated by its definition. An SSA definition therefore reaches a + // control flow node if it is the _closest_ SSA definition that dominates + // the node. If two definitions dominate a node then one must dominate the + // other, so therefore the definition of _closest_ is given by the dominator + // tree. Thus, reaching definitions can be calculated in terms of dominance. idom = bb.getImmediateDominator() ) } @@ -811,8 +772,7 @@ module Ssa { */ cached predicate ssaDefReachesEndOfBlock(BasicBlock bb, TrackedDefinition def, TrackedVar v) { - exists(int last | - last = maxSsaRefRank(bb, v) | + exists(int last | last = maxSsaRefRank(bb, v) | ssaDefReachesRank(bb, def, last, v) and liveAtExit(bb, v, _) ) @@ -828,7 +788,9 @@ module Ssa { * The read at `node` is of kind `rk`. */ cached - predicate ssaDefReachesRead(TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk) { + predicate ssaDefReachesRead( + TrackedVar v, TrackedDefinition def, ControlFlow::Node read, ReadKind rk + ) { ssaDefReachesReadWithinBlock(v, def, read, rk) or exists(BasicBlock bb | @@ -843,7 +805,9 @@ module Ssa { * definition `redef` without crossing another SSA definition of `v`. */ cached - predicate ssaDefReachesUncertainDef(TrackedVar v, TrackedDefinition def, UncertainDefinition redef) { + predicate ssaDefReachesUncertainDef( + TrackedVar v, TrackedDefinition def, UncertainDefinition redef + ) { ssaDefReachesUncertainDefWithinBlock(v, def, redef) or exists(BasicBlock bb | @@ -882,7 +846,6 @@ module Ssa { } import Cached } - private import SsaDefReaches /** @@ -947,9 +910,7 @@ module Ssa { } private class FieldOrPropDefinition extends AssignableDefinition { - FieldOrPropDefinition() { - this.getTarget() instanceof FieldOrProp - } + FieldOrPropDefinition() { this.getTarget() instanceof FieldOrProp } } /** @@ -957,22 +918,21 @@ module Ssa { * SSA update, since it is an initialization and therefore cannot alias. */ private predicate init(FieldOrPropDefinition fpdef) { - exists(FieldOrPropAccess access | - access = fpdef.getTargetAccess() | + exists(FieldOrPropAccess access | access = fpdef.getTargetAccess() | fpdef.getEnclosingCallable() instanceof Constructor and ownFieldOrPropAccess(access) or exists(LocalVariable v | v.getAnAccess() = access.getQualifier() and not v.isCaptured() and - forex(AssignableDefinition def | - def.getTarget() = v and exists(def.getSource()) | + forex(AssignableDefinition def | def.getTarget() = v and exists(def.getSource()) | def.getSource() instanceof ObjectCreation ) ) ) or - fpdef.(AssignableDefinitions::AssignmentDefinition).getAssignment() instanceof MemberInitializer + fpdef.(AssignableDefinitions::AssignmentDefinition).getAssignment() instanceof + MemberInitializer } /** @@ -990,8 +950,7 @@ module Ssa { * for SSA construction. */ private predicate setsOwnFieldOrProp(InstanceCallable c, FieldOrProp fp) { - exists(FieldOrPropDefinition fpdef | - relevantDefinition(c, fp, fpdef) | + exists(FieldOrPropDefinition fpdef | relevantDefinition(c, fp, fpdef) | ownFieldOrPropAccess(fpdef.getTargetAccess()) ) } @@ -1001,8 +960,7 @@ module Ssa { * construction excluding those cases covered by `setsOwnFieldOrProp`. */ private predicate setsOtherFieldOrProp(Callable c, FieldOrProp fp) { - exists(FieldOrPropDefinition fpdef | - relevantDefinition(c, fp, fpdef) | + exists(FieldOrPropDefinition fpdef | relevantDefinition(c, fp, fpdef) | not ownFieldOrPropAccess(fpdef.getTargetAccess()) ) } @@ -1040,8 +998,7 @@ module Ssa { */ Callable getARuntimeTarget(Call c) { // Non-delegate call: use dispatch library - exists(DispatchCall dc | - dc.getCall() = c | + exists(DispatchCall dc | dc.getCall() = c | result = dc.getADynamicTarget().getSourceDeclaration() ) or @@ -1068,16 +1025,18 @@ module Ssa { } /** Holds if expression `e` is a delegate creation for callable `c` of type `t`. */ - private predicate delegateCreation(Expr e, Callable c, SystemLinqExpressions::DelegateExtType dt) { + private predicate delegateCreation( + Expr e, Callable c, SystemLinqExpressions::DelegateExtType dt + ) { e = any(AnonymousFunctionExpr afe | - dt = afe.getType() and - c = afe - ) + dt = afe.getType() and + c = afe + ) or e = any(CallableAccess ca | - c = ca.getTarget().getSourceDeclaration() and - dt = ca.getType() - ) + c = ca.getTarget().getSourceDeclaration() and + dt = ca.getType() + ) } private predicate delegateFlowStep(Expr pred, Expr succ) { @@ -1085,7 +1044,8 @@ module Ssa { or exists(Call call, Callable callable | callable.getSourceDeclaration().canReturn(pred) and - call = succ | + call = succ + | callable = call.getTarget() or callable = call.getTarget().(Method).getAnOverrider+() or callable = call.getTarget().(Method).getAnUltimateImplementor() or @@ -1096,14 +1056,14 @@ module Ssa { or exists(AssignableDefinition def, Assignable a | a instanceof Field or - a instanceof Property | + a instanceof Property + | a = def.getTarget() and succ.(AssignableRead) = a.getAnAccess() and pred = def.getSource() ) or - exists(AddEventExpr ae | - succ.(EventAccess).getTarget() = ae.getTarget() | + exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() | pred = ae.getRValue() ) } @@ -1111,13 +1071,10 @@ module Ssa { private predicate reachableFromDelegateCreation(Expr e) { delegateCreation(e, _, _) or - exists(Expr mid | - reachableFromDelegateCreation(mid) | - delegateFlowStep(mid, e) - ) + exists(Expr mid | reachableFromDelegateCreation(mid) | delegateFlowStep(mid, e)) } - pragma [noinline] + pragma[noinline] private predicate delegateFlowStepReachable(Expr pred, Expr succ) { delegateFlowStep(pred, succ) and reachableFromDelegateCreation(pred) @@ -1155,15 +1112,16 @@ module Ssa { * Holds if a call to `x.c` can change the value of `x.fp`. The actual * update occurs in `setter`. */ - private predicate setsOwnFieldOrPropTransitive(InstanceCallable c, FieldOrProp fp, InstanceCallable setter) { + private predicate setsOwnFieldOrPropTransitive( + InstanceCallable c, FieldOrProp fp, InstanceCallable setter + ) { setsOwnFieldOrProp(setter, fp) and // `intraInstanceCallEdge*(c, setter)` applies `fastTC` and therefore misses // important magic optimization; consequently apply magic manually by explicit // recursion c = setter or - exists(InstanceCallable mid | - setsOwnFieldOrPropTransitive(mid, fp, setter) | + exists(InstanceCallable mid | setsOwnFieldOrPropTransitive(mid, fp, setter) | intraInstanceCallEdge(c, mid) ) } @@ -1210,10 +1168,7 @@ module Ssa { generalSetter(_, f.getAssignable(), _) ) or - exists(Callable mid | - pruneFromLeft(mid) | - callEdge(mid, c) - ) + exists(Callable mid | pruneFromLeft(mid) | callEdge(mid, c)) } /** @@ -1224,41 +1179,38 @@ module Ssa { relevantDefinition(c, _, _) and pruneFromLeft(c) or - exists(Callable mid | - pruneFromRight(mid) | + exists(Callable mid | pruneFromRight(mid) | callEdge(c, mid) and pruneFromLeft(c) ) } - private class PrunedCallable extends Callable { - PrunedCallable() { - pruneFromRight(this) - } - } + private class PrunedCallable extends Callable { PrunedCallable() { pruneFromRight(this) } } - private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { - callEdge(c1, c2) - } + private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) } private predicate callEdgePrunedPlus(PrunedCallable c1, PrunedCallable c2) = fastTC(callEdgePruned/2)(c1, c2) - pragma [noinline] - private predicate updatesNamedFieldOrPropPart1Prefix0(Call call, TrackedFieldOrProp tfp, Callable c1, FieldOrProp fp) { + pragma[noinline] + private predicate updatesNamedFieldOrPropPart1Prefix0( + Call call, TrackedFieldOrProp tfp, Callable c1, FieldOrProp fp + ) { updateCandidate(_, _, tfp, call) and fp = tfp.getAssignable() and generalSetter(_, fp, _) and c1 = getARuntimeTarget(call) } - pragma [noinline] + pragma[noinline] private predicate relevantDefinitionProj(PrunedCallable c, FieldOrProp fp) { relevantDefinition(c, fp, _) } - pragma [noopt] - predicate updatesNamedFieldOrPropPart1Prefix(Call call, TrackedFieldOrProp tfp, Callable c1, Callable setter, FieldOrProp fp) { + pragma[noopt] + predicate updatesNamedFieldOrPropPart1Prefix( + Call call, TrackedFieldOrProp tfp, Callable c1, Callable setter, FieldOrProp fp + ) { updatesNamedFieldOrPropPart1Prefix0(call, tfp, c1, fp) and relevantDefinitionProj(setter, fp) and (c1 = setter or callEdgePrunedPlus(c1, setter)) @@ -1268,11 +1220,14 @@ module Ssa { * Holds if `call` may change the value of `tfp` on some instance, which may or * may not alias with `this`. The actual update occurs in `setter`. */ - pragma [noopt] - private predicate updatesNamedFieldOrPropPart1(Call call, TrackedFieldOrProp tfp, Callable setter) { + pragma[noopt] + private predicate updatesNamedFieldOrPropPart1( + Call call, TrackedFieldOrProp tfp, Callable setter + ) { exists(Callable c1, Callable c2, FieldOrProp fp | updatesNamedFieldOrPropPart1Prefix(call, tfp, c1, setter, fp) and - generalSetter(c2, fp, setter) | + generalSetter(c2, fp, setter) + | c1 = c2 or callEdgePrunedPlus(c1, c2) ) } @@ -1281,12 +1236,16 @@ module Ssa { * Holds if `call` may change the value of `tfp` on `this`. The actual update occurs * in `setter`. */ - private predicate updatesNamedFieldOrPropPart2(Call call, TrackedFieldOrProp tfp, Callable setter) { + private predicate updatesNamedFieldOrPropPart2( + Call call, TrackedFieldOrProp tfp, Callable setter + ) { updateCandidate(_, _, tfp, call) and setsOwnFieldOrPropTransitive(getARuntimeTarget(call), tfp.getAssignable(), setter) } - private predicate updatesNamedFieldOrPropPossiblyLive(BasicBlock bb, int i, TrackedFieldOrProp fp, Call call, Callable setter) { + private predicate updatesNamedFieldOrPropPossiblyLive( + BasicBlock bb, int i, TrackedFieldOrProp fp, Call call, Callable setter + ) { updateCandidate(bb, i, fp, call) and ( updatesNamedFieldOrPropPart1(call, fp, setter) @@ -1307,13 +1266,11 @@ module Ssa { cached predicate updatesNamedFieldOrProp(Call c, TrackedFieldOrProp fp, Callable setter) { forceCachingInSameStage() and - exists(BasicBlock bb, int i | - updatesNamedFieldOrPropPossiblyLive(bb, i, fp, c, setter) | + exists(BasicBlock bb, int i | updatesNamedFieldOrPropPossiblyLive(bb, i, fp, c, setter) | not exists(firstRefAfterCall(bb, i, fp)) and liveAtExit(bb, fp, _) or - exists(int j | - j = firstRefAfterCall(bb, i, fp) | + exists(int j | j = firstRefAfterCall(bb, i, fp) | liveAtRank(bb, j, fp, _, _) and not ref(bb, j, fp, Write(true)) ) @@ -1347,15 +1304,13 @@ module Ssa { not exists(firstRefAfterQualifiedDef(bb, i, q)) and liveAtExit(bb, q, _) or - exists(int j | - j = firstRefAfterQualifiedDef(bb, i, q) | + exists(int j | j = firstRefAfterQualifiedDef(bb, i, q) | liveAtRank(bb, j, q, _, _) and not ref(bb, j, q, Write(true)) ) ) } } - private import FieldOrPropsImpl /** @@ -1389,8 +1344,7 @@ module Ssa { */ private class CapturedWrittenLocalScopeVariable extends LocalScopeVariable { CapturedWrittenLocalScopeVariable() { - exists(AssignableDefinition def | - def.getTarget() = this | + exists(AssignableDefinition def | def.getTarget() = this | def.getEnclosingCallable() != this.getCallable() ) } @@ -1412,7 +1366,10 @@ module Ssa { * Holds if `vdef` is an update of captured variable `v` in callable `c` * that is relevant for SSA construction. */ - private predicate relevantDefinition(Callable c, CapturedWrittenLocalScopeVariable v, CapturedWrittenLocalScopeVariableDefinition vdef) { + private predicate relevantDefinition( + Callable c, CapturedWrittenLocalScopeVariable v, + CapturedWrittenLocalScopeVariableDefinition vdef + ) { exists(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable sv | vdef.getTarget() = v and vdef.getEnclosingCallable() = c and @@ -1428,7 +1385,9 @@ module Ssa { * `v` has an update somewhere, and `v` is likely to be live in `bb` at index * `i`. */ - private predicate updateCandidate(BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, Call call) { + private predicate updateCandidate( + BasicBlock bb, int i, CapturedWrittenLocalScopeSourceVariable v, Call call + ) { possiblyLiveAtAllNodes(bb, v) and callAt(bb, i, call) and relevantDefinition(_, v.getAssignable(), _) @@ -1445,10 +1404,7 @@ module Ssa { relevantDefinition(_, v.getAssignable(), _) ) or - exists(Callable mid | - pruneFromLeft(mid) | - callEdge(mid, c) - ) + exists(Callable mid | pruneFromLeft(mid) | callEdge(mid, c)) } /** @@ -1459,33 +1415,29 @@ module Ssa { relevantDefinition(c, _, _) and pruneFromLeft(c) or - exists(Callable mid | - pruneFromRight(mid) | + exists(Callable mid | pruneFromRight(mid) | callEdge(c, mid) and pruneFromLeft(c) ) } - private class PrunedCallable extends Callable { - PrunedCallable() { - pruneFromRight(this) - } - } + private class PrunedCallable extends Callable { PrunedCallable() { pruneFromRight(this) } } - private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { - callEdge(c1, c2) - } + private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) } private predicate callEdgePrunedPlus(PrunedCallable c1, PrunedCallable c2) = fastTC(callEdgePruned/2)(c1, c2) - pragma [noinline] + pragma[noinline] private predicate relevantDefinitionProj(PrunedCallable c, CapturedWrittenLocalScopeVariable v) { relevantDefinition(c, v, _) } - pragma [noinline] - private predicate updatesCapturedVariablePrefix(Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable c, CapturedWrittenLocalScopeVariable captured) { + pragma[noinline] + private predicate updatesCapturedVariablePrefix( + Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable c, + CapturedWrittenLocalScopeVariable captured + ) { updateCandidate(_, _, v, call) and captured = v.getAssignable() and relevantDefinitionProj(_, captured) and @@ -1499,8 +1451,10 @@ module Ssa { * may be the callable that introduces `v`, in which case `call` is not an * actual update. */ - pragma [noopt] - private predicate updatesCapturedVariableWriter(Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable writer) { + pragma[noopt] + private predicate updatesCapturedVariableWriter( + Call call, CapturedWrittenLocalScopeSourceVariable v, PrunedCallable writer + ) { exists(PrunedCallable c, CapturedWrittenLocalScopeVariable captured | updatesCapturedVariablePrefix(call, v, c, captured) and relevantDefinitionProj(writer, captured) and @@ -1512,10 +1466,11 @@ module Ssa { * Holds if `call` may change the value of captured variable `v`. The actual * update occurs in `def`. */ - private predicate updatesCapturedVariablePossiblyLive(BasicBlock bb, int i, Call call, LocalScopeSourceVariable v, AssignableDefinition def) { + private predicate updatesCapturedVariablePossiblyLive( + BasicBlock bb, int i, Call call, LocalScopeSourceVariable v, AssignableDefinition def + ) { updateCandidate(bb, i, v, call) and - exists(Callable writer | - relevantDefinition(writer, v.getAssignable(), def) | + exists(Callable writer | relevantDefinition(writer, v.getAssignable(), def) | updatesCapturedVariableWriter(call, v, writer) ) } @@ -1530,22 +1485,21 @@ module Ssa { * update occurs in `def`. */ cached - predicate updatesCapturedVariable(Call call, LocalScopeSourceVariable v, AssignableDefinition def) { + predicate updatesCapturedVariable( + Call call, LocalScopeSourceVariable v, AssignableDefinition def + ) { forceCachingInSameStage() and - exists(BasicBlock bb, int i | - updatesCapturedVariablePossiblyLive(bb, i, call, v, def) | + exists(BasicBlock bb, int i | updatesCapturedVariablePossiblyLive(bb, i, call, v, def) | not exists(firstRefAfter(bb, i, v)) and liveAtExit(bb, v, _) or - exists(int j | - j = firstRefAfter(bb, i, v) | + exists(int j | j = firstRefAfter(bb, i, v) | liveAtRank(bb, j, v, _, _) and not ref(bb, j, v, Write(true)) ) ) } } - private import CapturedVariableImpl /** @@ -1578,7 +1532,8 @@ module Ssa { */ private predicate capturerReads(Callable c, LocalScopeVariable v) { exists(ControlFlow::BasicBlocks::EntryBlock ebb, LocalScopeSourceVariable lssv | - liveAtEntry(ebb, lssv, _) | + liveAtEntry(ebb, lssv, _) + | v = lssv.getAssignable() and c = ebb.getCallable() and v.getCallable() != c @@ -1589,9 +1544,7 @@ module Ssa { * A local scope variable that is captured, and read by at least one capturer. */ private class CapturedReadLocalScopeVariable extends LocalScopeVariable { - CapturedReadLocalScopeVariable() { - capturerReads(_, this) - } + CapturedReadLocalScopeVariable() { capturerReads(_, this) } } private class CapturedReadLocalScopeSourceVariable extends LocalScopeSourceVariable { @@ -1600,7 +1553,9 @@ module Ssa { } } - private predicate capturedVariableWrite(BasicBlock bb, int i, CapturedReadLocalScopeSourceVariable v) { + private predicate capturedVariableWrite( + BasicBlock bb, int i, CapturedReadLocalScopeSourceVariable v + ) { ref(bb, i, v, Write(_)) } @@ -1608,9 +1563,10 @@ module Ssa { * Holds if the write to captured source variable `v` at index `i` in basic * block `bb` may be read by a callable reachable from the call `c`. */ - private predicate implicitReadCandidate(BasicBlock bb, int i, Call c, CapturedReadLocalScopeSourceVariable v) { - exists(BasicBlock bb0, int i0 | - bb0.getNode(i0) = c.getAControlFlowNode() | + private predicate implicitReadCandidate( + BasicBlock bb, int i, Call c, CapturedReadLocalScopeSourceVariable v + ) { + exists(BasicBlock bb0, int i0 | bb0.getNode(i0) = c.getAControlFlowNode() | // `c` is in basic block `bb` capturedVariableWrite(bb0, i, v) and i < i0 and @@ -1629,16 +1585,16 @@ module Ssa { * block `bb` reaches the start of basic block `r`, without passing through * another write. */ - private predicate capturedVariableWriteReachesStartOf(BasicBlock bb, int i, BasicBlock r, CapturedReadLocalScopeSourceVariable v) { - exists(int last | - last = max(refRank(bb, _, v, Write(_))) | + private predicate capturedVariableWriteReachesStartOf( + BasicBlock bb, int i, BasicBlock r, CapturedReadLocalScopeSourceVariable v + ) { + exists(int last | last = max(refRank(bb, _, v, Write(_))) | last = refRank(bb, i, v, Write(_)) and capturedVariableWrite(bb, i, v) and r = bb.getASuccessor() ) or - exists(BasicBlock mid | - capturedVariableWriteReachesStartOf(bb, i, mid, v) | + exists(BasicBlock mid | capturedVariableWriteReachesStartOf(bb, i, mid, v) | r = mid.getASuccessor() and not capturedVariableWrite(mid, _, v) ) @@ -1654,10 +1610,7 @@ module Ssa { c = getARuntimeTarget(call) ) or - exists(Callable mid | - pruneFromLeft(mid) | - callEdge(mid, c) - ) + exists(Callable mid | pruneFromLeft(mid) | callEdge(mid, c)) } /** @@ -1671,28 +1624,24 @@ module Ssa { pruneFromLeft(c) ) or - exists(Callable mid | - pruneFromRight(mid) | + exists(Callable mid | pruneFromRight(mid) | callEdge(c, mid) and pruneFromLeft(c) ) } - private class PrunedCallable extends Callable { - PrunedCallable() { - pruneFromRight(this) - } - } + private class PrunedCallable extends Callable { PrunedCallable() { pruneFromRight(this) } } - private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { - callEdge(c1, c2) - } + private predicate callEdgePruned(PrunedCallable c1, PrunedCallable c2) { callEdge(c1, c2) } private predicate callEdgePrunedPlus(PrunedCallable c1, PrunedCallable c2) = fastTC(callEdgePruned/2)(c1, c2) - pragma [noinline] - private predicate readsCapturedVariablePrefix(Call call, CapturedReadLocalScopeSourceVariable v, PrunedCallable c, CapturedReadLocalScopeVariable captured) { + pragma[noinline] + private predicate readsCapturedVariablePrefix( + Call call, CapturedReadLocalScopeSourceVariable v, PrunedCallable c, + CapturedReadLocalScopeVariable captured + ) { implicitReadCandidate(_, _, call, v) and captured = v.getAssignable() and capturerReads(_, captured) and @@ -1706,8 +1655,10 @@ module Ssa { * may be a callable that writes to `v`, in which case `call` is not an * actual read. */ - pragma [noopt] - private predicate readsCapturedVariable(Call call, CapturedReadLocalScopeSourceVariable v, Callable reader) { + pragma[noopt] + private predicate readsCapturedVariable( + Call call, CapturedReadLocalScopeSourceVariable v, Callable reader + ) { exists(PrunedCallable c, CapturedReadLocalScopeVariable captured | readsCapturedVariablePrefix(call, v, c, captured) and capturerReads(reader, captured) and @@ -1739,9 +1690,10 @@ module Ssa { * The write to `i` inside `M2` on line 4 is live because of the implicit call * definition on line 5. */ - predicate liveAfterWriteCapturedOut(BasicBlock bb, int i, LocalScopeSourceVariable v, ImplicitCallDefinition def) { - exists(LocalScopeVariable lsv | - def.getSourceVariable().getAssignable() = lsv | + predicate liveAfterWriteCapturedOut( + BasicBlock bb, int i, LocalScopeSourceVariable v, ImplicitCallDefinition def + ) { + exists(LocalScopeVariable lsv | def.getSourceVariable().getAssignable() = lsv | lsv = v.getAssignable() and bb.getNode(i) = def.getAPossibleDefinition().getAControlFlowNode() ) @@ -1771,7 +1723,9 @@ module Ssa { * The write to `i` on line 5 is live because of the call to `M2` on line 6, which * reaches the entry definition for `i` in `M2` on line 4. */ - predicate liveAfterWriteCapturedIn(BasicBlock bb, int i, LocalScopeSourceVariable v, ImplicitEntryDefinition def, Call c) { + predicate liveAfterWriteCapturedIn( + BasicBlock bb, int i, LocalScopeSourceVariable v, ImplicitEntryDefinition def, Call c + ) { exists(Callable reader | implicitReadCandidate(bb, i, c, v) and readsCapturedVariable(c, v, reader) and @@ -1789,11 +1743,12 @@ module Ssa { liveAfterWriteCapturedIn(bb, i, v, _, _) } } - private import CapturedVariableLivenessImpl - private cached module SsaImpl { - cached predicate forceCachingInSameStage() { any() } + cached + private module SsaImpl { + cached + predicate forceCachingInSameStage() { any() } /** * A data type representing SSA definitions. @@ -1815,12 +1770,12 @@ module Ssa { * SSA definitions are only introduced where necessary. That is, dead assignments * have no associated SSA definitions. */ - cached newtype TDefinition = + cached + newtype TDefinition = TSsaExplicitDef(TrackedVar v, AssignableDefinition def, BasicBlock bb, int i) { variableDefinition(bb, i, v, def) and ( - exists(ReadKind rk | - liveAfterWrite(bb, i, v, rk) | + exists(ReadKind rk | liveAfterWrite(bb, i, v, rk) | // A `ref` assignment such as // ``` // ref int i = ref GetRef(); @@ -1828,35 +1783,35 @@ module Ssa { // is dead when there are no reads of or writes to `i`. // That is, the read kind `rk` witnessing the liveness of the assignment // must not be the pseudo read inserted at the end of the enclosing callable - not (rk = OutRefExitRead() and def.(AssignableDefinitions::AssignmentDefinition).getSource() instanceof RefExpr) - and + not ( + rk = OutRefExitRead() and + def.(AssignableDefinitions::AssignmentDefinition).getSource() instanceof RefExpr + ) and rk != CapturedVarExitRead() // Captured variables are handled below ) or liveAfterWriteCaptured(bb, i, v) ) - } - or + } or TSsaImplicitEntryDef(TrackedVar v, ControlFlow::BasicBlocks::EntryBlock ebb) { - liveAtEntry(ebb, v, _) - and + liveAtEntry(ebb, v, _) and exists(Callable c | c = ebb.getCallable() and - c = v.getEnclosingCallable() | + c = v.getEnclosingCallable() + | // Captured variable exists(LocalScopeVariable lsv | - v = any(LocalScopeSourceVariable lv | lsv = lv.getAssignable()) | + v = any(LocalScopeSourceVariable lv | lsv = lv.getAssignable()) + | lsv.getCallable() != c ) or // Each tracked field and property has an implicit entry definition v instanceof TrackedFieldOrProp ) - } - or + } or TSsaImplicitCallDef(TrackedVar v, Call c, BasicBlock bb, int i) { - bb.getNode(i) = c.getAControlFlowNode() - and + bb.getNode(i) = c.getAControlFlowNode() and ( // Liveness of `v` after `c` is guaranteed by `updatesNamedFieldOrProp` updatesNamedFieldOrProp(c, v, _) @@ -1864,8 +1819,7 @@ module Ssa { // Liveness of `v` after `c` is guaranteed by `updatesCapturedVariable` updatesCapturedVariable(c, v, _) ) - } - or + } or TSsaImplicitQualifierDef(TrackedVar v, Definition qdef) { exists(BasicBlock bb, int i | qdef.getSourceVariable() = v.getQualifier() and @@ -1878,13 +1832,11 @@ module Ssa { // for `x.M.M`. not exists(TSsaImplicitCallDef(v, _, bb, i)) ) - } - or + } or TSsaImplicitUntrackedDef(UntrackedVar v, BasicBlock bb, int i) { // Insert a definition prior to every read for untracked variables bb.getNode(i + 1) = v.getAnAccess().(AssignableRead).getAControlFlowNode() - } - or + } or TPhiNode(TrackedVar v, ControlFlow::BasicBlocks::JoinBlock bb) { phiNodeMaybeLive(bb, v) and liveAtEntry(bb, v, _) @@ -1892,8 +1844,7 @@ module Ssa { pragma[noinline] private predicate phiNodeMaybeLive(ControlFlow::BasicBlocks::JoinBlock bb, TrackedVar v) { - exists(Definition def, BasicBlock bb1 | - definesAt(def, bb1, _, v) | + exists(Definition def, BasicBlock bb1 | definesAt(def, bb1, _, v) | bb1.inDominanceFrontier(bb) ) } @@ -1904,26 +1855,26 @@ module Ssa { * fields/properties) are considered to be at index `-1`, while normal variable * updates are at the index of the control flow node they wrap. */ - cached predicate definesAt(Definition def, BasicBlock bb, int i, SourceVariable v) { + cached + predicate definesAt(Definition def, BasicBlock bb, int i, SourceVariable v) { def = TSsaExplicitDef(v, _, bb, i) or def = TSsaImplicitEntryDef(v, bb) and i = -1 or def = TSsaImplicitCallDef(v, _, bb, i) or - exists(Definition qdef | - def = TSsaImplicitQualifierDef(v, qdef) | - definesAt(qdef, bb, i, _) - ) + exists(Definition qdef | def = TSsaImplicitQualifierDef(v, qdef) | definesAt(qdef, bb, i, _)) or def = TSsaImplicitUntrackedDef(v, bb, i) or def = TPhiNode(v, bb) and i = -1 } - cached predicate isCapturedVariableDefinitionFlowIn(ExplicitDefinition def, ImplicitEntryDefinition edef, Call c) { - exists(BasicBlock bb, int i, LocalScopeSourceVariable v | - definesAt(def, bb, i, v) | + cached + predicate isCapturedVariableDefinitionFlowIn( + ExplicitDefinition def, ImplicitEntryDefinition edef, Call c + ) { + exists(BasicBlock bb, int i, LocalScopeSourceVariable v | definesAt(def, bb, i, v) | liveAfterWriteCapturedIn(bb, i, v, edef, c) ) } @@ -1934,21 +1885,21 @@ module Ssa { * callable. */ private predicate isLiveCapturedVariableDefinition(ExplicitDefinition def) { - exists(Definition def0 | - def = def0.getAnUltimateDefinition() | + exists(Definition def0 | def = def0.getAnUltimateDefinition() | ssaDefReachesRead(_, def0, _, CapturedVarExitRead()) ) } - cached predicate isCapturedVariableDefinitionFlowOut(ExplicitDefinition def, ImplicitCallDefinition cdef) { - exists(BasicBlock bb, int i, LocalScopeSourceVariable v | - definesAt(def, bb, i, v) | + cached + predicate isCapturedVariableDefinitionFlowOut( + ExplicitDefinition def, ImplicitCallDefinition cdef + ) { + exists(BasicBlock bb, int i, LocalScopeSourceVariable v | definesAt(def, bb, i, v) | liveAfterWriteCapturedOut(bb, i, v, cdef) and isLiveCapturedVariableDefinition(def) ) } } - private import SsaImpl private string getSplitString(Definition def) { @@ -2006,9 +1957,7 @@ module Ssa { * - The reads of `this.Field` on lines 10 and 11 can be reached from the phi * node between lines 9 and 10. */ - AssignableRead getARead() { - result = this.getAReadAtNode(_) - } + AssignableRead getARead() { result = this.getAReadAtNode(_) } /** * Gets a read of the source variable underlying this SSA definition at @@ -2228,9 +2177,7 @@ module Ssa { * this definition reaches the end of basic block `bb`, at which point it is still * live, without crossing another SSA definition of the same source variable. */ - predicate isLiveAtEndOfBlock(BasicBlock bb) { - ssaDefReachesEndOfBlock(bb, this, _) - } + predicate isLiveAtEndOfBlock(BasicBlock bb) { ssaDefReachesEndOfBlock(bb, this, _) } /** * Holds if this SSA definition is at index `i` in basic block `bb`. Phi nodes and @@ -2238,9 +2185,7 @@ module Ssa { * index `-1`, while normal variable updates are at the index of the control flow * node they wrap. */ - predicate definesAt(BasicBlock bb, int i) { - definesAt(this, bb, i, _) - } + predicate definesAt(BasicBlock bb, int i) { definesAt(this, bb, i, _) } /** Gets the basic block to which this SSA definition belongs. */ BasicBlock getBasicBlock() { this.definesAt(result, _) } @@ -2251,10 +2196,7 @@ module Ssa { * callable. Pseudo nodes have no associated syntax element. */ Element getElement() { - exists(BasicBlock bb, int i | - this.definesAt(bb, i) | - result = bb.getNode(i).getElement() - ) + exists(BasicBlock bb, int i | this.definesAt(bb, i) | result = bb.getNode(i).getElement()) } /** @@ -2263,7 +2205,8 @@ module Ssa { */ predicate isLiveOutRefParameterDefinition(Parameter p) { exists(Definition def, ControlFlow::Node read, SourceVariable v | - this = def.getAnUltimateDefinition() | + this = def.getAnUltimateDefinition() + | ssaDefReachesRead(v, def, read, OutRefExitRead()) and v.getAssignable() = p ) @@ -2281,11 +2224,10 @@ module Ssa { */ class ExplicitDefinition extends Definition, TSsaExplicitDef { TrackedVar tv; + AssignableDefinition ad; - ExplicitDefinition() { - this = TSsaExplicitDef(tv, ad, _, _) - } + ExplicitDefinition() { this = TSsaExplicitDef(tv, ad, _, _) } /** * Gets an underlying assignable definition. The result is always unique, @@ -2349,15 +2291,12 @@ module Ssa { override Element getElement() { result = ad.getElement() } override string toString() { - if this.getADefinition() instanceof AssignableDefinitions::ImplicitParameterDefinition then - result = getToStringPrefix(this) + "SSA param(" + this.getSourceVariable() + ")" - else - result = getToStringPrefix(this) + "SSA def(" + this.getSourceVariable() + ")" + if this.getADefinition() instanceof AssignableDefinitions::ImplicitParameterDefinition + then result = getToStringPrefix(this) + "SSA param(" + this.getSourceVariable() + ")" + else result = getToStringPrefix(this) + "SSA def(" + this.getSourceVariable() + ")" } - override Location getLocation() { - result = ad.getLocation() - } + override Location getLocation() { result = ad.getLocation() } } /** @@ -2394,15 +2333,12 @@ module Ssa { override Callable getElement() { result = this.getCallable() } override string toString() { - if this.getSourceVariable().getAssignable() instanceof LocalScopeVariable then - result = getToStringPrefix(this) + "SSA capture def(" + this.getSourceVariable() + ")" - else - result = getToStringPrefix(this) + "SSA entry def(" + this.getSourceVariable() + ")" + if this.getSourceVariable().getAssignable() instanceof LocalScopeVariable + then result = getToStringPrefix(this) + "SSA capture def(" + this.getSourceVariable() + ")" + else result = getToStringPrefix(this) + "SSA entry def(" + this.getSourceVariable() + ")" } - override Location getLocation() { - result = this.getCallable().getLocation() - } + override Location getLocation() { result = this.getCallable().getLocation() } } /** @@ -2410,9 +2346,7 @@ module Ssa { * via a call. */ class ImplicitCallDefinition extends ImplicitDefinition, TSsaImplicitCallDef { - Call getCall() { - this = TSsaImplicitCallDef(_, result, _, _) - } + Call getCall() { this = TSsaImplicitCallDef(_, result, _, _) } /** * Gets one of the definitions that may contribute to this implicit @@ -2421,8 +2355,7 @@ module Ssa { * and which targets the same assignable as this SSA definition. */ AssignableDefinition getAPossibleDefinition() { - exists(Callable setter | - updatesNamedFieldOrProp(getCall(), _, setter) | + exists(Callable setter | updatesNamedFieldOrProp(getCall(), _, setter) | result.getEnclosingCallable() = setter and result.getTarget() = this.getSourceVariable().getAssignable() ) @@ -2435,9 +2368,7 @@ module Ssa { result = getToStringPrefix(this) + "SSA call def(" + getSourceVariable() + ")" } - override Location getLocation() { - result = getCall().getLocation() - } + override Location getLocation() { result = getCall().getLocation() } } /** @@ -2446,17 +2377,13 @@ module Ssa { */ class ImplicitQualifierDefinition extends ImplicitDefinition, TSsaImplicitQualifierDef { /** Gets the SSA definition for the qualifier. */ - Definition getQualifierDefinition() { - this = TSsaImplicitQualifierDef(_, result) - } + Definition getQualifierDefinition() { this = TSsaImplicitQualifierDef(_, result) } override string toString() { result = getToStringPrefix(this) + "SSA qualifier def(" + getSourceVariable() + ")" } - override Location getLocation() { - result = getQualifierDefinition().getLocation() - } + override Location getLocation() { result = getQualifierDefinition().getLocation() } } /** @@ -2475,9 +2402,7 @@ module Ssa { result = getToStringPrefix(this) + "SSA untracked def(" + getSourceVariable() + ")" } - override Location getLocation() { - result = this.getARead().getLocation() - } + override Location getLocation() { result = this.getARead().getLocation() } } /** @@ -2487,9 +2412,7 @@ module Ssa { * Phi nodes are the canonical (and currently only) example. */ class PseudoDefinition extends Definition { - PseudoDefinition() { - this = TPhiNode(_, _) - } + PseudoDefinition() { this = TPhiNode(_, _) } /** * Gets an input of this pseudo definition. @@ -2544,6 +2467,7 @@ module Ssa { * Strictly speaking, the node is *before* the first node, but such a location * does not exist in the source program. */ + override Location getLocation() { exists(ControlFlow::BasicBlocks::JoinBlock bb | this = TPhiNode(_, bb) and @@ -2561,8 +2485,8 @@ module Ssa { class UncertainDefinition extends Definition { UncertainDefinition() { this = any(ExplicitDefinition def | - forex(AssignableDefinition ad | ad = def.getADefinition() | not ad.isCertain()) - ) + forex(AssignableDefinition ad | ad = def.getADefinition() | not ad.isCertain()) + ) or this instanceof ImplicitCallDefinition or @@ -2573,13 +2497,9 @@ module Ssa { * Gets the immediately preceding definition. Since this update is uncertain * the value from the preceding definition might still be valid. */ - Definition getPriorDefinition() { - ssaDefReachesUncertainDef(_, result, this) - } + Definition getPriorDefinition() { ssaDefReachesUncertainDef(_, result, this) } } /** INTERNAL: Do not use. */ - module Internal { - import SsaDefReaches - } + module Internal { import SsaDefReaches } } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll index 367358931b1..267378b01d7 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/BaseSSA.qll @@ -27,8 +27,7 @@ module BaseSsa { bb.getNode(i) = def.getAControlFlowNode() and v = def.getTarget() and // In cases like `(x, x) = (0, 1)`, we discard the first (dead) definition of `x` - not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | - first = def | + not exists(TupleAssignmentDefinition first, TupleAssignmentDefinition second | first = def | second.getAssignment() = first.getAssignment() and second.getEvaluationOrder() > first.getEvaluationOrder() and second.getTarget() = v @@ -40,14 +39,15 @@ module BaseSsa { * variable `v` in an SSA representation. */ private predicate needsPhiNode(BasicBlock bb, SimpleLocalScopeVariable v) { - exists(BasicBlock def | - def.inDominanceFrontier(bb) | + exists(BasicBlock def | def.inDominanceFrontier(bb) | defAt(def, _, _, v) or needsPhiNode(def, v) ) } - private newtype SsaRefKind = SsaRead() or SsaDef() + private newtype SsaRefKind = + SsaRead() or + SsaDef() /** * Holds if the `i`th node of basic block `bb` is a reference to `v`, @@ -80,11 +80,10 @@ module BaseSsa { * `bb` reaches the reference at rank `rnk`, without passing through another * definition of `v`, including phi nodes. */ - private predicate defReachesRank(BasicBlock bb, AssignableDefinition def, SimpleLocalScopeVariable v, int rnk) { - exists(int i | - rnk = ssaRefRank(bb, i, v, SsaDef()) | - defAt(bb, i, def, v) - ) + private predicate defReachesRank( + BasicBlock bb, AssignableDefinition def, SimpleLocalScopeVariable v, int rnk + ) { + exists(int i | rnk = ssaRefRank(bb, i, v, SsaDef()) | defAt(bb, i, def, v)) or defReachesRank(bb, def, v, rnk - 1) and rnk = ssaRefRank(bb, _, v, SsaRead()) @@ -112,7 +111,8 @@ module BaseSsa { * Gets a read of the SSA definition for variable `v` at definition `def`. That is, * a read that is guaranteed to read the value assigned at definition `def`. */ - cached AssignableRead getARead(AssignableDefinition def, SimpleLocalScopeVariable v) { + cached + AssignableRead getARead(AssignableDefinition def, SimpleLocalScopeVariable v) { exists(BasicBlock bb, int i, int rnk | result.getAControlFlowNode() = bb.getNode(i) and rnk = ssaRefRank(bb, i, v, SsaRead()) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll index ce48f7f82c8..4219e49eab6 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/Steps.qll @@ -18,8 +18,7 @@ module Steps { private AssignableRead getARead(AssignableDefinition def) { result = BaseSsa::getARead(def, _) or - exists(LocalScopeVariable v | - def.getTarget() = v | + exists(LocalScopeVariable v | def.getTarget() = v | result = v.getAnAccess() and strictcount(AssignableDefinition def0 | def0.getTarget() = v) = 1 ) @@ -27,7 +26,8 @@ module Steps { exists(Field f | def.getTarget() = f and result = f.getAnAccess() and - strictcount(AssignableDefinition def0 | def0.getTarget() = f) = 1 | + strictcount(AssignableDefinition def0 | def0.getTarget() = f) = 1 + | f.isReadOnly() or f.isConst() or isEffectivelyInternalOrPrivate(f) @@ -53,29 +53,26 @@ module Steps { } private predicate flowIn(Parameter p, Expr pred, AssignableRead succ) { - exists(AssignableDefinitions::ImplicitParameterDefinition def, Call c | - succ = getARead(def) | + exists(AssignableDefinitions::ImplicitParameterDefinition def, Call c | succ = getARead(def) | pred = getArgumentForOverridderParameter(c, p) and p.getSourceDeclaration() = def.getParameter() ) } private Expr getArgumentForOverridderParameter(Call call, Parameter p) { - exists(Parameter base, Callable callable | - result = call.getArgumentForParameter(base) | + exists(Parameter base, Callable callable | result = call.getArgumentForParameter(base) | base = callable.getAParameter() and isOverriderParameter(callable, p, base.getPosition()) ) } - pragma [noinline] + pragma[noinline] private predicate isOverriderParameter(Callable c, Parameter p, int i) { ( p = c.getAParameter() or p = c.(Method).getAnOverrider+().getAParameter() or p = c.(Method).getAnUltimateImplementor().getAParameter() - ) - and + ) and i = p.getPosition() } @@ -130,13 +127,9 @@ module Steps { * ``` */ predicate stepOpen(Expr pred, Expr succ) { - exists(AssignableDefinition def | - succ = getARead(def) | - pred = def.getSource() - ) + exists(AssignableDefinition def | succ = getARead(def) | pred = def.getSource()) or - exists(Parameter p | - flowIn(p, pred, succ) | + exists(Parameter p | flowIn(p, pred, succ) | isEffectivelyInternalOrPrivateCallable(p.getCallable()) ) or diff --git a/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll index 80c03685e35..f433b2706af 100644 --- a/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/src/semmle/code/csharp/dispatch/Dispatch.qll @@ -39,35 +39,29 @@ class DispatchCall extends Internal::TDispatchCall { /** Internal implementation details. */ private module Internal { - private cached module Cached { + cached + private module Cached { /** Internal representation of calls. */ cached newtype TDispatchCall = TDispatchMethodCall(MethodCall mc) { not isReflectionCall(mc, _, _, _, _) and not mc.isLateBound() - } - or - TDispatchAccessorCall(AccessorCall ac) - or + } or + TDispatchAccessorCall(AccessorCall ac) or TDispatchReflectionCall(MethodCall mc, string name, Expr object, Expr qualifier, int args) { isReflectionCall(mc, name, object, qualifier, args) - } - or - TDispatchDynamicMethodCall(DynamicMethodCall dmc) - or - TDispatchDynamicOperatorCall(DynamicOperatorCall doc) - or - TDispatchDynamicMemberAccess(DynamicMemberAccess dma) - or - TDispatchDynamicElementAccess(DynamicElementAccess dea) - or - TDispatchDynamicEventAccess(AssignArithmeticOperation aao, DynamicMemberAccess dma, string name) { + } or + TDispatchDynamicMethodCall(DynamicMethodCall dmc) or + TDispatchDynamicOperatorCall(DynamicOperatorCall doc) or + TDispatchDynamicMemberAccess(DynamicMemberAccess dma) or + TDispatchDynamicElementAccess(DynamicElementAccess dea) or + TDispatchDynamicEventAccess( + AssignArithmeticOperation aao, DynamicMemberAccess dma, string name + ) { isPotentialEventCall(aao, dma, name) - } - or - TDispatchDynamicObjectCreation(DynamicObjectCreation doc) - or + } or + TDispatchDynamicObjectCreation(DynamicObjectCreation doc) or TDispatchStaticCall(Call c) { c = any(ObjectCreation oc | not oc.isLateBound()) or @@ -79,19 +73,13 @@ private module Internal { } cached - Expr getCall(DispatchCall dc) { - result = dc.(DispatchCallImpl).getCall() - } + Expr getCall(DispatchCall dc) { result = dc.(DispatchCallImpl).getCall() } cached - Expr getArgument(DispatchCall dc, int i) { - result = dc.(DispatchCallImpl).getArgument(i) - } + Expr getArgument(DispatchCall dc, int i) { result = dc.(DispatchCallImpl).getArgument(i) } cached - Expr getQualifier(DispatchCall dc) { - result = dc.(DispatchCallImpl).getQualifier() - } + Expr getQualifier(DispatchCall dc) { result = dc.(DispatchCallImpl).getQualifier() } cached RuntimeCallable getADynamicTarget(DispatchCall dc) { @@ -100,9 +88,7 @@ private module Internal { } import Cached - Callable getAStaticTarget(DispatchCall dc) { - result = dc.(DispatchCallImpl).getAStaticTarget() - } + Callable getAStaticTarget(DispatchCall dc) { result = dc.(DispatchCallImpl).getAStaticTarget() } /** * Holds if `mc` is a reflection call to a method named `name`, where @@ -110,7 +96,9 @@ private module Internal { * static method is invoked) and `qualifier` is the qualifier of the * reflection call. */ - private predicate isReflectionCall(MethodCall mc, string name, Expr object, Expr qualifier, int args) { + private predicate isReflectionCall( + MethodCall mc, string name, Expr object, Expr qualifier, int args + ) { exists(SystemTypeClass stc | mc.getTarget() = stc.getInvokeMemberMethod() and mc.getArgument(0).getValue() = name and @@ -155,11 +143,14 @@ private module Internal { * potential event access and `name` is the name of the relevant event * accessor. */ - private predicate isPotentialEventCall(AssignArithmeticOperation aao, DynamicMemberAccess dma, string name) { + private predicate isPotentialEventCall( + AssignArithmeticOperation aao, DynamicMemberAccess dma, string name + ) { exists(DynamicOperatorCall doc, AssignExpr ae | ae = aao.getExpandedAssignment() and dma = ae.getLValue() and - doc = ae.getRValue() | + doc = ae.getRValue() + | aao instanceof AssignAddExpr and name = "add_" + dma.getLateBoundTargetName() or @@ -169,7 +160,7 @@ private module Internal { } /** A call. */ - private abstract class DispatchCallImpl extends TDispatchCall { + abstract private class DispatchCallImpl extends TDispatchCall { /** Gets a textual representation of this call. */ string toString() { none() } @@ -180,9 +171,7 @@ private module Internal { abstract Expr getArgument(int i); /** Gets the number of arguments of this call. */ - int getNumberOfArguments() { - result = count(int i | exists(getArgument(i))) - } + int getNumberOfArguments() { result = count(int i | exists(getArgument(i))) } /** Gets the qualifier of this call, if any. */ abstract Expr getQualifier(); @@ -199,8 +188,7 @@ private module Internal { * the qualifier is guaranteed not to be a subtype of `qualifierType`. */ predicate hasQualifierType(Type qualifierType, boolean isExactType) { - exists(Type trackedType | - trackedType = getAPossibleType(this.getQualifier(), isExactType) | + exists(Type trackedType | trackedType = getAPossibleType(this.getQualifier(), isExactType) | qualifierType = trackedType and not qualifierType instanceof TypeParameter or @@ -213,18 +201,15 @@ private module Internal { * that does not contain type parameters. */ TypeWithoutTypeParameters getANonExactQualifierTypeWithoutTypeParameters() { - exists(Type qualifierType | - hasQualifierType(qualifierType, false) | + exists(Type qualifierType | hasQualifierType(qualifierType, false) | // Qualifier type contains no type parameters: use it result = qualifierType or // Qualifier type is a constructed type where all type arguments are type // parameters: use the unbound generic type exists(ConstructedType ct | - ct = qualifierType - and - forex(Type arg | arg = ct.getATypeArgument() | arg instanceof TypeParameter) - and + ct = qualifierType and + forex(Type arg | arg = ct.getATypeArgument() | arg instanceof TypeParameter) and result = ct.getUnboundGeneric() ) or @@ -249,8 +234,13 @@ private module Internal { */ private Type getAPossibleType(Expr e, boolean isExact) { exists(ValueOrRefType qualifierType, FieldOrProperty fp, boolean qualifierTypeIsExact | - qualifierType = getAPossibleTypeDynamicMemberAccessQualifier(e, qualifierTypeIsExact, fp) | - (if qualifierTypeIsExact = true then qualifierType.hasMember(fp) else fp.getDeclaringType().isImplicitlyConvertibleTo(qualifierType)) and + qualifierType = getAPossibleTypeDynamicMemberAccessQualifier(e, qualifierTypeIsExact, fp) + | + ( + if qualifierTypeIsExact = true + then qualifierType.hasMember(fp) + else fp.getDeclaringType().isImplicitlyConvertibleTo(qualifierType) + ) and result = fp.getType() and isExact = false ) @@ -259,7 +249,9 @@ private module Internal { result = getASourceType(e, isExact) } - private Type getAPossibleTypeDynamicMemberAccessQualifier(DynamicMemberAccess dma, boolean isExact, FieldOrProperty fp) { + private Type getAPossibleTypeDynamicMemberAccessQualifier( + DynamicMemberAccess dma, boolean isExact, FieldOrProperty fp + ) { result = getAPossibleType(dma.getQualifier(), isExact) and fp.getName() = dma.getLateBoundTargetName() } @@ -278,8 +270,7 @@ private module Internal { or t.getAChild*() instanceof DynamicType or - exists(Type other | - other != t | + exists(Type other | other != t | not other instanceof DynamicType and other.isImplicitlyConvertibleTo(t) ) @@ -299,7 +290,8 @@ private module Internal { or exists(Assignable a | a instanceof Field or - a instanceof Property | + a instanceof Property + | succ.(AssignableRead) = a.getAnAccess() and pred = a.getAnAssignedValue() and a = any(Modifiable m | m.isEffectivelyInternal() or m.isEffectivelyPrivate()) @@ -314,12 +306,9 @@ private module Internal { typeMayBeImprecise(succ.getType()) } - private predicate stepTC(Expr succ, Expr pred) = - fastTC(stepExpr/2)(succ, pred) + private predicate stepTC(Expr succ, Expr pred) = fastTC(stepExpr/2)(succ, pred) - private class Source extends Expr { - Source() { not stepExpr(this, _) } - } + private class Source extends Expr { Source() { not stepExpr(this, _) } } private class Sink extends Expr { Sink() { @@ -329,7 +318,8 @@ private module Internal { or this = any(DispatchReflectionOrDynamicCall c).getArgument(_) or - this = any(MethodCall mc | mc.getTarget() = any(SystemObjectClass c).getGetTypeMethod()).getQualifier() + this = any(MethodCall mc | mc.getTarget() = any(SystemObjectClass c).getGetTypeMethod()) + .getQualifier() or this = any(DispatchCallImpl c).getQualifier() } @@ -347,7 +337,8 @@ private module Internal { Type getASourceType(Sink e, boolean isExact) { exists(Source s | s = e.getASource() or - s = e | + s = e + | result = s.getType() and if hasExactType(s) then isExact = true else isExact = false ) @@ -362,25 +353,18 @@ private module Internal { * into account. */ private class DispatchMethodCall extends DispatchCallImpl, TDispatchMethodCall { - override MethodCall getCall() { - this = TDispatchMethodCall(result) - } + override MethodCall getCall() { this = TDispatchMethodCall(result) } override Expr getArgument(int i) { - exists(Call call, Parameter p | - call = this.getCall() | + exists(Call call, Parameter p | call = this.getCall() | p = call.getTarget().getParameter(i) and result = call.getArgumentForParameter(p) ) } - override Expr getQualifier() { - result = getCall().getQualifier() - } + override Expr getQualifier() { result = getCall().getQualifier() } - override Method getAStaticTarget() { - result = getCall().getTarget() - } + override Method getAStaticTarget() { result = getCall().getTarget() } override RuntimeMethod getADynamicTarget() { result = getViableInherited() @@ -489,29 +473,19 @@ private module Internal { * into account. */ private class DispatchAccessorCall extends DispatchCallImpl, TDispatchAccessorCall { - override AccessorCall getCall() { - this = TDispatchAccessorCall(result) - } + override AccessorCall getCall() { this = TDispatchAccessorCall(result) } - override Expr getArgument(int i) { - result = getCall().getArgument(i) - } + override Expr getArgument(int i) { result = getCall().getArgument(i) } - override Expr getQualifier() { - result = getCall().(MemberAccess).getQualifier() - } + override Expr getQualifier() { result = getCall().(MemberAccess).getQualifier() } - override Accessor getAStaticTarget() { - result = getCall().getTarget() - } + override Accessor getAStaticTarget() { result = getCall().getTarget() } override RuntimeAccessor getADynamicTarget() { - result = getADynamicTargetCandidate() - and + result = getADynamicTargetCandidate() and // Calls to accessors may have `dynamic` expression arguments, // so we need to check that the types match - forall(Type argumentType, int i | - hasDynamicArg(i, argumentType) | + forall(Type argumentType, int i | hasDynamicArg(i, argumentType) | argumentType.isImplicitlyConvertibleTo(result.getParameter(i).getType()) ) } @@ -576,7 +550,7 @@ private module Internal { ) } - pragma [noinline] + pragma[noinline] private predicate hasQualifierTypeSourceDecl(SourceDeclarationType t) { exists(Type qualifierType | this.hasQualifierType(qualifierType, _) and @@ -629,7 +603,7 @@ private module Internal { } /** An internal helper class for comparing two types modulo type parameters. */ - private abstract class StructurallyComparedModuloTypeParameters extends Type { + abstract private class StructurallyComparedModuloTypeParameters extends Type { /** Gets a candidate for comparison against this type. */ abstract Type getACandidate(); @@ -657,9 +631,7 @@ private module Internal { * by different types at different positions. For example, * `C` is considered a potential instantiation of `C`. */ - TypeWithoutTypeParameters getAPotentialInstance() { - equalsModuloTypeParameters(result) - } + TypeWithoutTypeParameters getAPotentialInstance() { equalsModuloTypeParameters(result) } } private Type candidateInternal(Type t) { @@ -674,8 +646,7 @@ private module Internal { /** Holds if types `x` and `y` are equal modulo type parameters. */ private predicate sameModuloTypeParameters(Type x, Type y) { - y = candidateInternal(x) - and + y = candidateInternal(x) and ( x = y or @@ -683,21 +654,18 @@ private module Internal { or y instanceof TypeParameter or + // They must have the same kind. ( - // They must have the same kind. - ( - x instanceof PointerType and y instanceof PointerType - or - x instanceof NullableType and y instanceof NullableType - or - x.(ArrayType).hasSameShapeAs((ArrayType)y) - or - x.(ConstructedType).getUnboundGeneric() = y.(ConstructedType).getUnboundGeneric() - ) - and - // All of their corresponding children must be structurally equal - sameChildrenModuloTypeParameters(x, y, x.getNumberOfChildren() - 1) - ) + x instanceof PointerType and y instanceof PointerType + or + x instanceof NullableType and y instanceof NullableType + or + x.(ArrayType).hasSameShapeAs(y.(ArrayType)) + or + x.(ConstructedType).getUnboundGeneric() = y.(ConstructedType).getUnboundGeneric() + ) and + // All of their corresponding children must be structurally equal + sameChildrenModuloTypeParameters(x, y, x.getNumberOfChildren() - 1) ) } @@ -713,8 +681,7 @@ private module Internal { sameModuloTypeParameters(xChild, yChild) ) or - exists(Type xChild, Type yChild | - sameChildrenModuloTypeParameters(x, y, i - 1) | + exists(Type xChild, Type yChild | sameChildrenModuloTypeParameters(x, y, i - 1) | candidateChildren(x, i, xChild, yChild) and yChild = y.getChild(i) and sameModuloTypeParameters(xChild, yChild) @@ -722,8 +689,7 @@ private module Internal { } private predicate candidateChildren(Type x, int i, Type xChild, Type yChild) { - exists(Type y | - y = candidateInternal(x) | + exists(Type y | y = candidateInternal(x) | xChild = x.getChild(i) and yChild = y.getChild(i) ) @@ -735,22 +701,19 @@ private module Internal { */ private class QualifierTypeWithTypeParameters extends StructurallyComparedModuloTypeParameters { QualifierTypeWithTypeParameters() { - containsTypeParameters() - and - any(DispatchCallImpl dc).hasQualifierType(this, false) - and + containsTypeParameters() and + any(DispatchCallImpl dc).hasQualifierType(this, false) and exists(Type arg | arg = getAChild() | not arg instanceof TypeParameter) } override ConstructedType getACandidate() { - not result.containsTypeParameters() - and + not result.containsTypeParameters() and this.(ConstructedType).getUnboundGeneric() = result.getUnboundGeneric() } } /** A reflection-based call or a call using dynamic types. */ - private abstract class DispatchReflectionOrDynamicCall extends DispatchCallImpl { + abstract private class DispatchReflectionOrDynamicCall extends DispatchCallImpl { /** Gets the name of the callable being called in this call. */ abstract string getName(); @@ -792,8 +755,7 @@ private module Internal { this.hasQualifierType(result, true) or // Non-exact qualifier type - exists(Type qualifierType | - this.hasNonExactQualifierType(qualifierType) | + exists(Type qualifierType | this.hasNonExactQualifierType(qualifierType) | result = getANonExactQualifierSubType(qualifierType) ) } @@ -807,29 +769,23 @@ private module Internal { * `dynamic`). */ private predicate hasUnknownQualifierType() { - exists(Type qualifierType | - this.hasNonExactQualifierType(qualifierType) | + exists(Type qualifierType | this.hasNonExactQualifierType(qualifierType) | isUnknownType(qualifierType) ) } - /* - * The set of static targets is all callables with matching - * names and number of parameters. This set is further reduced in - * `getADynamicTarget()` by taking type information into account. - */ + // The set of static targets is all callables with matching + // names and number of parameters. This set is further reduced in + // `getADynamicTarget()` by taking type information into account. override Callable getAStaticTarget() { - result = getACallableWithMatchingName() - and + result = getACallableWithMatchingName() and exists(int minArgs | minArgs = count(Parameter p | - p = result.getAParameter() and - not p.hasDefaultValue() and - not p.isParams() - ) - and - getNumberOfArguments() >= minArgs - and + p = result.getAParameter() and + not p.hasDefaultValue() and + not p.isParams() + ) and + getNumberOfArguments() >= minArgs and (result.(Method).hasParams() or getNumberOfArguments() <= result.getNumberOfParameters()) ) } @@ -841,29 +797,25 @@ private module Internal { result.getName() = getName() } - /* - * A callable is viable if the following conditions are all satisfied: - * - * 1. It is a viable candidate (see `getADynamicTargetCandidate()`). - * 2. The argument types are compatible with the parameter types. Here, - * type compatibility means that an argument type must be implicitly - * convertible to a type that equals the corresponding parameter type - * modulo type parameters. For example, an argument type `int` is - * compatible with a parameter type `IEquatable`, because `int` is - * implicitly convertible to `IEquatable`, which equals - * `IEquatable` modulo type parameters. Note that potential type - * parameter constraints are not taken into account, nor is the - * possibility of matching a given type parameter with multiple, - * conflicting types (for example, `Tuple` is considered - * compatible with `Tuple`). - */ + // A callable is viable if the following conditions are all satisfied: + // + // 1. It is a viable candidate (see `getADynamicTargetCandidate()`). + // 2. The argument types are compatible with the parameter types. Here, + // type compatibility means that an argument type must be implicitly + // convertible to a type that equals the corresponding parameter type + // modulo type parameters. For example, an argument type `int` is + // compatible with a parameter type `IEquatable`, because `int` is + // implicitly convertible to `IEquatable`, which equals + // `IEquatable` modulo type parameters. Note that potential type + // parameter constraints are not taken into account, nor is the + // possibility of matching a given type parameter with multiple, + // conflicting types (for example, `Tuple` is considered + // compatible with `Tuple`). override RuntimeCallable getADynamicTarget() { // Condition 1 - result = getADynamicTargetCandidate() - and + result = getADynamicTargetCandidate() and // Condition 2 - forall(int i | - i in [0 .. getNumberOfArguments() - 1] | + forall(int i | i in [0 .. getNumberOfArguments() - 1] | result = getADynamicTargetCandidateWithCompatibleArg(i) ) } @@ -873,13 +825,13 @@ private module Internal { result = getADynamicTargetCandidateWithCompatibleArg2(i) } - pragma [noinline] + pragma[noinline] private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg1(int i) { - result = this.getADynamicTargetCandidate() - and + result = this.getADynamicTargetCandidate() and exists(Type parameterType, Type argumentType | parameterType = this.getAParameterType(result, i) and - argumentType = getAPossibleType(this.getArgument(i), _) | + argumentType = getAPossibleType(this.getArgument(i), _) + | argumentType.isImplicitlyConvertibleTo(parameterType) or argumentType instanceof NullType and @@ -891,10 +843,8 @@ private module Internal { } private Type getAParameterType(RuntimeCallable c, int i) { - exists(this.getArgument(i)) - and - c = this.getADynamicTargetCandidate() - and + exists(this.getArgument(i)) and + c = this.getADynamicTargetCandidate() and ( result = c.getParameter(i).getType() or @@ -903,18 +853,16 @@ private module Internal { ) } - pragma [noinline] + pragma[noinline] private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg2(int i) { - result = this.getADynamicTargetCandidate() - and - exists(Type parameterType, Type t | - parameterType = this.getAParameterType(result, i) | + result = this.getADynamicTargetCandidate() and + exists(Type parameterType, Type t | parameterType = this.getAParameterType(result, i) | this.argumentConvConstExpr(i, t) and t.isImplicitlyConvertibleTo(parameterType) ) } - pragma [noinline] + pragma[noinline] private predicate argumentConvConstExpr(int i, Type t) { convConstantExpr(this.getArgument(i), t) } @@ -931,8 +879,7 @@ private module Internal { * type of one of the arguments. */ RuntimeCallable getADynamicTargetCandidate() { - result = getAStaticTarget() - and + result = getAStaticTarget() and ( result = getADynamicTargetCandidateInstanceMethod(this.getAQualifierType()) or @@ -948,14 +895,14 @@ private module Internal { ) } - pragma [noinline] + pragma[noinline] private RuntimeOperator getADynamicTargetCandidateOperator() { result = getAStaticTarget() and result.getDeclaringType() = result.getAParameter().getType() } } - pragma [noinline] + pragma[noinline] private RuntimeInstanceMethod getADynamicTargetCandidateInstanceMethod(RefType qualifierType) { exists(DispatchReflectionOrDynamicCall c | result = c.getAStaticTarget() and @@ -963,7 +910,7 @@ private module Internal { ) } - pragma [noinline] + pragma[noinline] private RuntimeInstanceAccessor getADynamicTargetCandidateInstanceAccessor(RefType qualifierType) { exists(DispatchReflectionOrDynamicCall c | result = c.getAStaticTarget() and @@ -976,7 +923,7 @@ private module Internal { t instanceof ObjectType } - pragma [noinline] + pragma[noinline] private RefType getANonExactQualifierSubType(Type qualifierType) { isRelevantReflectionOrDynamicQualifierType(result) and result.isImplicitlyConvertibleTo(qualifierType) and @@ -984,29 +931,32 @@ private module Internal { not result instanceof NullType // null types are implicitly convertible to all types, but not actual subtypes } - pragma [noinline] + pragma[noinline] private predicate isRelevantReflectionOrDynamicQualifierType(RefType rt) { rt.hasCallable(any(DispatchReflectionOrDynamicCall c).getAStaticTarget()) } - private predicate reflectionOrDynamicArgEqualsParamModuloTypeParameters(Type argumentType, Type parameterType) { - exists(Type t | - reflectionOrDynamicArgumentTypeIsImplicitlyConvertibleTo(argumentType,t) | - t.(ReflectionOrDynamicCallArgumentWithTypeParameters).equalsModuloTypeParameters(parameterType) + private predicate reflectionOrDynamicArgEqualsParamModuloTypeParameters( + Type argumentType, Type parameterType + ) { + exists(Type t | reflectionOrDynamicArgumentTypeIsImplicitlyConvertibleTo(argumentType, t) | + t + .(ReflectionOrDynamicCallArgumentWithTypeParameters) + .equalsModuloTypeParameters(parameterType) ) } - pragma [noinline] - private predicate reflectionOrDynamicArgumentTypeIsImplicitlyConvertibleTo(Type argumentType, Type t) { + pragma[noinline] + private predicate reflectionOrDynamicArgumentTypeIsImplicitlyConvertibleTo( + Type argumentType, Type t + ) { isReflectionOrDynamicArgumentType(argumentType) and argumentType.isImplicitlyConvertibleTo(t) } - pragma [noinline] + pragma[noinline] private predicate isReflectionOrDynamicArgumentType(Type t) { - exists(DispatchReflectionOrDynamicCall c | - t = getAPossibleType(c.getArgument(_), _) - ) + exists(DispatchReflectionOrDynamicCall c | t = getAPossibleType(c.getArgument(_), _)) } /** @@ -1017,17 +967,19 @@ private module Internal { */ private predicate isReflectionOrDynamicCallArgumentWithTypeParameters(Type argType, Type paramType) { exists(DispatchReflectionOrDynamicCall call, Parameter p, int i, int j | - p = call.getAStaticTarget().getParameter(i) - and - if p.isParams() then ( - j >= i and - paramType = p.getType().(ArrayType).getElementType() - ) else ( - i = j and - paramType = p.getType() - ) - and - argType = getAPossibleType(call.getArgument(j), _) | + p = call.getAStaticTarget().getParameter(i) and + ( + if p.isParams() + then ( + j >= i and + paramType = p.getType().(ArrayType).getElementType() + ) else ( + i = j and + paramType = p.getType() + ) + ) and + argType = getAPossibleType(call.getArgument(j), _) + | argType.containsTypeParameters() or paramType.containsTypeParameters() @@ -1050,14 +1002,11 @@ private module Internal { } /** A call using reflection. */ - private class DispatchReflectionCall extends DispatchReflectionOrDynamicCall, TDispatchReflectionCall { - override MethodCall getCall() { - this = TDispatchReflectionCall(result, _, _, _, _) - } + private class DispatchReflectionCall extends DispatchReflectionOrDynamicCall, + TDispatchReflectionCall { + override MethodCall getCall() { this = TDispatchReflectionCall(result, _, _, _, _) } - override string getName() { - this = TDispatchReflectionCall(_, result, _, _, _) - } + override string getName() { this = TDispatchReflectionCall(_, result, _, _, _) } override Expr getQualifier() { this = TDispatchReflectionCall(_, _, result, _, _) and @@ -1067,10 +1016,8 @@ private module Internal { /** Gets the type containing the static callable being called, if any. */ private ValueOrRefType getStaticType() { exists(Expr object, Expr qualifier | - this = TDispatchReflectionCall(_, _, object, qualifier, _) - and - object instanceof NullLiteral - and + this = TDispatchReflectionCall(_, _, object, qualifier, _) and + object instanceof NullLiteral and ( result = getAMethodCallArgSource(qualifier).(TypeofExpr).getTypeAccess().getType() or @@ -1095,48 +1042,38 @@ private module Internal { // Does not take named arguments into account override Expr getArgument(int i) { exists(int args, ArrayCreation ac | - this = TDispatchReflectionCall(_, _, _, _, args) - and - ac = getAMethodCallArgSource(getCall().getArgument(args)) - and + this = TDispatchReflectionCall(_, _, _, _, args) and + ac = getAMethodCallArgSource(getCall().getArgument(args)) and result = ac.getInitializer().getElement(i) ) } } /** A method call using dynamic types. */ - private class DispatchDynamicMethodCall extends DispatchReflectionOrDynamicCall, TDispatchDynamicMethodCall { - override DynamicMethodCall getCall() { - this = TDispatchDynamicMethodCall(result) - } + private class DispatchDynamicMethodCall extends DispatchReflectionOrDynamicCall, + TDispatchDynamicMethodCall { + override DynamicMethodCall getCall() { this = TDispatchDynamicMethodCall(result) } - override string getName() { - result = getCall().getLateBoundTargetName() - } + override string getName() { result = getCall().getLateBoundTargetName() } - override Expr getQualifier() { - result = getCall().getQualifier() - } + override Expr getQualifier() { result = getCall().getQualifier() } override RuntimeMethod getADynamicTargetCandidate() { - if exists(getCall().getTarget()) then + if exists(getCall().getTarget()) + then // static method call result = getCall().getTarget() - else - result = DispatchReflectionOrDynamicCall.super.getADynamicTargetCandidate() + else result = DispatchReflectionOrDynamicCall.super.getADynamicTargetCandidate() } // Does not take named arguments into account - override Expr getArgument(int i) { - result = getCall().getArgument(i) - } + override Expr getArgument(int i) { result = getCall().getArgument(i) } } /** An operator call using dynamic types. */ - private class DispatchDynamicOperatorCall extends DispatchReflectionOrDynamicCall, TDispatchDynamicOperatorCall { - override DynamicOperatorCall getCall() { - this = TDispatchDynamicOperatorCall(result) - } + private class DispatchDynamicOperatorCall extends DispatchReflectionOrDynamicCall, + TDispatchDynamicOperatorCall { + override DynamicOperatorCall getCall() { this = TDispatchDynamicOperatorCall(result) } override string getName() { exists(Operator o | @@ -1145,33 +1082,25 @@ private module Internal { ) } - override Expr getQualifier() { - none() - } + override Expr getQualifier() { none() } - override Expr getArgument(int i) { - result = getCall().getArgument(i) - } + override Expr getArgument(int i) { result = getCall().getArgument(i) } } /** A (potential) call to a property accessor using dynamic types. */ - private class DispatchDynamicMemberAccess extends DispatchReflectionOrDynamicCall, TDispatchDynamicMemberAccess { - override DynamicMemberAccess getCall() { - this = TDispatchDynamicMemberAccess(result) - } + private class DispatchDynamicMemberAccess extends DispatchReflectionOrDynamicCall, + TDispatchDynamicMemberAccess { + override DynamicMemberAccess getCall() { this = TDispatchDynamicMemberAccess(result) } override string getName() { - exists(DynamicMemberAccess dma | - dma = getCall() | + exists(DynamicMemberAccess dma | dma = getCall() | result = "get_" + dma.(DynamicMemberRead).getLateBoundTargetName() or result = "set_" + dma.(DynamicMemberWrite).getLateBoundTargetName() ) } - override Expr getQualifier() { - result = getCall().getQualifier() - } + override Expr getQualifier() { result = getCall().getQualifier() } override Expr getArgument(int i) { // Only calls to setters have an argument @@ -1184,27 +1113,22 @@ private module Internal { } /** A (potential) call to an indexer accessor using dynamic types. */ - private class DispatchDynamicElementAccess extends DispatchReflectionOrDynamicCall, TDispatchDynamicElementAccess { - override DynamicElementAccess getCall() { - this = TDispatchDynamicElementAccess(result) - } + private class DispatchDynamicElementAccess extends DispatchReflectionOrDynamicCall, + TDispatchDynamicElementAccess { + override DynamicElementAccess getCall() { this = TDispatchDynamicElementAccess(result) } override string getName() { - exists(DynamicElementAccess dea | - dea = getCall() | + exists(DynamicElementAccess dea | dea = getCall() | dea instanceof DynamicElementRead and result = "get_Item" or dea instanceof DynamicElementWrite and result = "set_Item" ) } - override Expr getQualifier() { - result = getCall().getQualifier() - } + override Expr getQualifier() { result = getCall().getQualifier() } override Expr getArgument(int i) { - exists(DynamicElementAccess dea | - dea = getCall() | + exists(DynamicElementAccess dea | dea = getCall() | result = dea.getIndex(i) or // Calls to setters have an extra argument @@ -1216,71 +1140,51 @@ private module Internal { } /** A (potential) call to an event accessor using dynamic types. */ - private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall, TDispatchDynamicEventAccess { + private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall, + TDispatchDynamicEventAccess { override AssignArithmeticOperation getCall() { this = TDispatchDynamicEventAccess(result, _, _) } - override string getName() { - this = TDispatchDynamicEventAccess(_, _, result) - } + override string getName() { this = TDispatchDynamicEventAccess(_, _, result) } override Expr getQualifier() { - result = any(DynamicMemberAccess dma | this = TDispatchDynamicEventAccess(_, dma, _)).getQualifier() + result = any(DynamicMemberAccess dma | this = TDispatchDynamicEventAccess(_, dma, _)) + .getQualifier() } - override Expr getArgument(int i) { - i = 0 and result = getCall().getRValue() - } + override Expr getArgument(int i) { i = 0 and result = getCall().getRValue() } } /** A call to a constructor using dynamic types. */ - private class DispatchDynamicObjectCreation extends DispatchReflectionOrDynamicCall, TDispatchDynamicObjectCreation { - override DynamicObjectCreation getCall() { - this = TDispatchDynamicObjectCreation(result) - } + private class DispatchDynamicObjectCreation extends DispatchReflectionOrDynamicCall, + TDispatchDynamicObjectCreation { + override DynamicObjectCreation getCall() { this = TDispatchDynamicObjectCreation(result) } - override string getName() { - none() - } + override string getName() { none() } - override Expr getQualifier() { - none() - } + override Expr getQualifier() { none() } - override Expr getArgument(int i) { - result = getCall().getArgument(i) - } + override Expr getArgument(int i) { result = getCall().getArgument(i) } - override RuntimeCallable getADynamicTargetCandidate() { - result = getCall().getTarget() - } + override RuntimeCallable getADynamicTargetCandidate() { result = getCall().getTarget() } } /** A call where the target can be resolved statically. */ private class DispatchStaticCall extends DispatchCallImpl, TDispatchStaticCall { - override Call getCall() { - this = TDispatchStaticCall(result) - } + override Call getCall() { this = TDispatchStaticCall(result) } - override Expr getQualifier() { - none() - } + override Expr getQualifier() { none() } override Expr getArgument(int i) { - exists(Call call, Parameter p | - call = this.getCall() | + exists(Call call, Parameter p | call = this.getCall() | p = call.getTarget().getParameter(i) and result = call.getArgumentForParameter(p) ) } - override Callable getAStaticTarget() { - result = getCall().getTarget() - } + override Callable getAStaticTarget() { result = getCall().getTarget() } - override RuntimeCallable getADynamicTarget() { - result = getCall().getTarget() - } + override RuntimeCallable getADynamicTarget() { result = getCall().getTarget() } } } diff --git a/csharp/ql/src/semmle/code/csharp/dispatch/OverridableCallable.qll b/csharp/ql/src/semmle/code/csharp/dispatch/OverridableCallable.qll index 8527546a5a8..3e2a3119bfc 100644 --- a/csharp/ql/src/semmle/code/csharp/dispatch/OverridableCallable.qll +++ b/csharp/ql/src/semmle/code/csharp/dispatch/OverridableCallable.qll @@ -2,6 +2,7 @@ * Provides classes that define callables that can be overridden or * implemented. */ + import csharp /** @@ -134,8 +135,7 @@ class OverridableCallable extends Callable { * - `C2.M = C2.M.getInherited(C3)`. */ Callable getInherited(SourceDeclarationType t) { - exists(Callable sourceDecl | - result = getInherited1(t, sourceDecl) | + exists(Callable sourceDecl | result = getInherited1(t, sourceDecl) | hasSourceDeclarationCallable(t, sourceDecl) ) } @@ -159,13 +159,13 @@ class OverridableCallable extends Callable { sourceDecl = result.getSourceDeclaration() } - pragma [noinline] + pragma[noinline] private ValueOrRefType hasOverrider(Callable c) { c = this.getAnOverrider*() and result = c.getDeclaringType() } - pragma [noinline] + pragma[noinline] private ValueOrRefType hasOverridingImplementor(Callable c) { c = this.getAnOverridingImplementor() and result = c.getDeclaringType() @@ -207,10 +207,8 @@ class OverridableCallable extends Callable { } private TypeWithoutTypeParameters getAnOverriderBaseType(ValueOrRefType t) { - exists(getAnOverriderAux(t)) - and - exists(Type t0 | - t0 = t.getABaseType*() | + exists(getAnOverriderAux(t)) and + exists(Type t0 | t0 = t.getABaseType*() | result = t0 or result = t0.(ConstructedType).getUnboundGeneric() @@ -238,8 +236,7 @@ class OverridableCallable extends Callable { } private predicate declaredInTypeWithTypeParameters() { - exists(ValueOrRefType t | - t = getDeclaringType() | + exists(ValueOrRefType t | t = getDeclaringType() | t.containsTypeParameters() or // Access to a local callable, `this.M()`, in a generic class @@ -250,27 +247,18 @@ class OverridableCallable extends Callable { } } -pragma [noinline] +pragma[noinline] private predicate hasSourceDeclarationCallable(ValueOrRefType t, Callable sourceDecl) { - exists(Callable c | - t.hasCallable(c) | - sourceDecl = c.getSourceDeclaration() - ) + exists(Callable c | t.hasCallable(c) | sourceDecl = c.getSourceDeclaration()) } /** An overridable method. */ class OverridableMethod extends Method, OverridableCallable { - override Method getAnOverrider() { - result = Method.super.getAnOverrider() - } + override Method getAnOverrider() { result = Method.super.getAnOverrider() } - override Method getAnImplementor(ValueOrRefType t) { - result = Method.super.getAnImplementor(t) - } + override Method getAnImplementor(ValueOrRefType t) { result = Method.super.getAnImplementor(t) } - override Method getAnUltimateImplementor() { - result = Method.super.getAnUltimateImplementor() - } + override Method getAnUltimateImplementor() { result = Method.super.getAnUltimateImplementor() } override Method getInherited(SourceDeclarationType t) { result = OverridableCallable.super.getInherited(t) @@ -283,9 +271,7 @@ class OverridableMethod extends Method, OverridableCallable { /** An overridable accessor. */ class OverridableAccessor extends Accessor, OverridableCallable { - override Accessor getAnOverrider() { - overrides(result, this) - } + override Accessor getAnOverrider() { overrides(result, this) } override Accessor getAnImplementor(ValueOrRefType t) { exists(Virtualizable implementor, int kind | @@ -337,14 +323,10 @@ private int getAccessorKind(Accessor a) { /** A type not containing type parameters. */ class TypeWithoutTypeParameters extends Type { - TypeWithoutTypeParameters() { - not containsTypeParameters() - } + TypeWithoutTypeParameters() { not containsTypeParameters() } } /** A source declared type. */ class SourceDeclarationType extends TypeWithoutTypeParameters { - SourceDeclarationType() { - this = getSourceDeclaration() - } + SourceDeclarationType() { this = getSourceDeclaration() } } diff --git a/csharp/ql/src/semmle/code/csharp/dispatch/RuntimeCallable.qll b/csharp/ql/src/semmle/code/csharp/dispatch/RuntimeCallable.qll index ff9a046c690..039efc6830f 100644 --- a/csharp/ql/src/semmle/code/csharp/dispatch/RuntimeCallable.qll +++ b/csharp/ql/src/semmle/code/csharp/dispatch/RuntimeCallable.qll @@ -3,6 +3,7 @@ * those callables that may actually be called at run-time (that is, neither * abstract callables nor callables defined in an interface). */ + import csharp private import cil private import dotnet @@ -25,17 +26,11 @@ class RuntimeMethod extends RuntimeCallable { this instanceof CIL::Method } - predicate isStatic() { - this.(Method).isStatic() or this.(CIL::Method).isStatic() - } + predicate isStatic() { this.(Method).isStatic() or this.(CIL::Method).isStatic() } } /** A run-time instance method. */ -class RuntimeInstanceMethod extends RuntimeMethod { - RuntimeInstanceMethod() { - not isStatic() - } -} +class RuntimeInstanceMethod extends RuntimeMethod { RuntimeInstanceMethod() { not isStatic() } } /** A run-time operator. */ class RuntimeOperator extends Operator, RuntimeCallable { } @@ -45,7 +40,5 @@ class RuntimeAccessor extends Accessor, RuntimeCallable { } /** A run-time instance accessor. */ class RuntimeInstanceAccessor extends RuntimeAccessor { - RuntimeInstanceAccessor() { - not isStatic() - } + RuntimeInstanceAccessor() { not isStatic() } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll index 196f1e5fe5c..ad8f2e9f2a4 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll @@ -23,16 +23,17 @@ class Access extends Expr, @access_expr { /** * An internal helper module to calculate accesses and their targets. */ -private cached module AccessImpl { - cached predicate isAccess(@access_expr ae) { +cached +private module AccessImpl { + cached + predicate isAccess(@access_expr ae) { isLocalVariableAccess(ae) implies exists(getLocalVariableAccessTarget(ae)) } - private predicate isLocalVariableAccess(@local_variable_access a) { - any() - } + private predicate isLocalVariableAccess(@local_variable_access a) { any() } - cached LocalVariable getLocalVariableAccessTarget(@local_variable_access a) { + cached + LocalVariable getLocalVariableAccessTarget(@local_variable_access a) { result = getLocalVariableAccessTargetNoDecl(a) or result = getLocalVariableAccessTargetDecl(a) } @@ -74,9 +75,7 @@ private cached module AccessImpl { * ``` */ class ThisAccess extends Access, @this_access_expr { - override Class getTarget() { - result = this.getEnclosingCallable().getDeclaringType() - } + override Class getTarget() { result = this.getEnclosingCallable().getDeclaringType() } override string toString() { result = "this access" } } @@ -108,8 +107,7 @@ class BaseAccess extends Access, @base_access_expr { */ class MemberAccess extends Access, QualifiableExpr, @member_access_expr { override predicate hasImplicitThisQualifier() { - QualifiableExpr.super.hasImplicitThisQualifier() - and + QualifiableExpr.super.hasImplicitThisQualifier() and not exists(MemberInitializer mi | mi.getLValue() = this) } @@ -132,17 +130,13 @@ class AssignableAccess extends Access, @assignable_access_expr { * Holds if this access passes the assignable being accessed as an `out` * argument in a method call. */ - predicate isOutArgument() { - expr_argument(this, 2) - } + predicate isOutArgument() { expr_argument(this, 2) } /** * Holds if this access passes the assignable being accessed as a `ref` * argument in a method call. */ - predicate isRefArgument() { - expr_argument(this, 1) - } + predicate isRefArgument() { expr_argument(this, 1) } /** * Holds if this access passes the assignable being accessed as an `out` @@ -157,9 +151,7 @@ class AssignableAccess extends Access, @assignable_access_expr { * Holds if this access passes the assignable being accessed as an `in` * argument in a method call. */ - predicate isInArgument() { - expr_argument(this, 3) - } + predicate isInArgument() { expr_argument(this, 3) } } /** @@ -167,9 +159,7 @@ class AssignableAccess extends Access, @assignable_access_expr { * (`LocalScopeVariableAccess`) or an access to a field (`FieldAccess`). */ class VariableAccess extends AssignableAccess, @variable_access_expr { - override Variable getTarget() { - expr_access(this, result) - } + override Variable getTarget() { expr_access(this, result) } } /** @@ -178,13 +168,9 @@ class VariableAccess extends AssignableAccess, @variable_access_expr { * access to a field (`FieldRead`). */ class VariableRead extends VariableAccess, AssignableRead { - override VariableRead getANextRead() { - result = AssignableRead.super.getANextRead() - } + override VariableRead getANextRead() { result = AssignableRead.super.getANextRead() } - override VariableRead getAReachableRead() { - result = AssignableRead.super.getAReachableRead() - } + override VariableRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() } } /** @@ -199,9 +185,7 @@ class VariableWrite extends VariableAccess, AssignableWrite { } * (`ParameterAccess`) or an access to a local variable (`LocalVariableAccess`). */ class LocalScopeVariableAccess extends VariableAccess, @local_scope_variable_access_expr { - override LocalScopeVariable getTarget() { - expr_access(this, result) - } + override LocalScopeVariable getTarget() { expr_access(this, result) } } /** @@ -210,9 +194,7 @@ class LocalScopeVariableAccess extends VariableAccess, @local_scope_variable_acc * (`LocalVariableRead`). */ class LocalScopeVariableRead extends LocalScopeVariableAccess, VariableRead { - override LocalScopeVariableRead getANextRead() { - result = VariableRead.super.getANextRead() - } + override LocalScopeVariableRead getANextRead() { result = VariableRead.super.getANextRead() } override LocalScopeVariableRead getAReachableRead() { result = VariableRead.super.getAReachableRead() @@ -236,13 +218,9 @@ class LocalScopeVariableWrite extends LocalScopeVariableAccess, VariableWrite { * ``` */ class ParameterAccess extends LocalScopeVariableAccess, @parameter_access_expr { - override Parameter getTarget() { - expr_access(this, result) - } + override Parameter getTarget() { expr_access(this, result) } - override string toString() { - result = "access to parameter " + this.getTarget().getName() - } + override string toString() { result = "access to parameter " + this.getTarget().getName() } } /** @@ -256,9 +234,7 @@ class ParameterAccess extends LocalScopeVariableAccess, @parameter_access_expr { * ``` */ class ParameterRead extends ParameterAccess, LocalScopeVariableRead { - override ParameterRead getANextRead() { - result = LocalScopeVariableRead.super.getANextRead() - } + override ParameterRead getANextRead() { result = LocalScopeVariableRead.super.getANextRead() } override ParameterRead getAReachableRead() { result = LocalScopeVariableRead.super.getAReachableRead() @@ -289,9 +265,7 @@ class ParameterWrite extends ParameterAccess, VariableWrite { } * ``` */ class LocalVariableAccess extends LocalScopeVariableAccess, @local_variable_access { - override LocalVariable getTarget() { - result = AccessImpl::getLocalVariableAccessTarget(this) - } + override LocalVariable getTarget() { result = AccessImpl::getLocalVariableAccessTarget(this) } override string toString() { // If this access is also a local variable declaration (that is, an `out` declared @@ -313,9 +287,7 @@ class LocalVariableAccess extends LocalScopeVariableAccess, @local_variable_acce * ``` */ class LocalVariableRead extends LocalVariableAccess, LocalScopeVariableRead { - override LocalVariableRead getANextRead() { - result = LocalScopeVariableRead.super.getANextRead() - } + override LocalVariableRead getANextRead() { result = LocalScopeVariableRead.super.getANextRead() } override LocalVariableRead getAReachableRead() { result = LocalScopeVariableRead.super.getAReachableRead() @@ -350,13 +322,9 @@ class LocalVariableWrite extends LocalVariableAccess, VariableWrite { } * ``` */ class FieldAccess extends AssignableMemberAccess, VariableAccess, @field_access_expr { - override Field getTarget() { - expr_access(this, result) - } + override Field getTarget() { expr_access(this, result) } - override string toString() { - result = "access to field " + this.getTarget().getName() - } + override string toString() { result = "access to field " + this.getTarget().getName() } } /** @@ -420,9 +388,7 @@ library class PropertyAccessExpr extends Expr, @property_access_expr { /** Gets the target of this property access. */ Property getProperty() { expr_access(this, result) } - override string toString() { - result = "access to property " + this.getProperty().getName() - } + override string toString() { result = "access to property " + this.getProperty().getName() } } /** @@ -457,13 +423,9 @@ class PropertyAccess extends AssignableMemberAccess, PropertyAccessExpr { * ``` */ class PropertyRead extends PropertyAccess, AssignableRead { - override PropertyRead getANextRead() { - result = AssignableRead.super.getANextRead() - } + override PropertyRead getANextRead() { result = AssignableRead.super.getANextRead() } - override PropertyRead getAReachableRead() { - result = AssignableRead.super.getAReachableRead() - } + override PropertyRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() } } /** @@ -497,9 +459,7 @@ class PropertyWrite extends PropertyAccess, AssignableWrite { } * ``` */ class TrivialPropertyAccess extends PropertyAccess { - TrivialPropertyAccess() { - this.getTarget() instanceof TrivialProperty - } + TrivialPropertyAccess() { this.getTarget() instanceof TrivialProperty } } /** @@ -517,9 +477,7 @@ class TrivialPropertyAccess extends PropertyAccess { * ``` */ class VirtualPropertyAccess extends PropertyAccess { - VirtualPropertyAccess() { - this.targetIsOverridableOrImplementable() - } + VirtualPropertyAccess() { this.targetIsOverridableOrImplementable() } } /** @@ -582,9 +540,7 @@ library class IndexerAccessExpr extends Expr, @indexer_access_expr { * ``` */ class IndexerAccess extends AssignableMemberAccess, ElementAccess, IndexerAccessExpr { - override Indexer getTarget() { - result = getIndexer() - } + override Indexer getTarget() { result = getIndexer() } override Indexer getQualifiedDeclaration() { result = ElementAccess.super.getQualifiedDeclaration() @@ -606,13 +562,9 @@ class IndexerAccess extends AssignableMemberAccess, ElementAccess, IndexerAccess * ``` */ class IndexerRead extends IndexerAccess, AssignableRead { - override IndexerRead getANextRead() { - result = AssignableRead.super.getANextRead() - } + override IndexerRead getANextRead() { result = AssignableRead.super.getANextRead() } - override IndexerRead getAReachableRead() { - result = AssignableRead.super.getAReachableRead() - } + override IndexerRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() } } /** @@ -645,9 +597,7 @@ class IndexerWrite extends IndexerAccess, AssignableWrite { } * } */ class VirtualIndexerAccess extends IndexerAccess { - VirtualIndexerAccess() { - targetIsOverridableOrImplementable() - } + VirtualIndexerAccess() { targetIsOverridableOrImplementable() } } /** @@ -656,13 +606,9 @@ class VirtualIndexerAccess extends IndexerAccess { */ library class EventAccessExpr extends Expr, @event_access_expr { /** Gets the target of this event access. */ - Event getEvent() { - expr_access(this, result) - } + Event getEvent() { expr_access(this, result) } - override string toString() { - result = "access to event " + this.getEvent().getName() - } + override string toString() { result = "access to event " + this.getEvent().getName() } } /** @@ -741,9 +687,7 @@ class EventWrite extends EventAccess, AssignableWrite { } * ``` */ class VirtualEventAccess extends EventAccess { - VirtualEventAccess() { - targetIsOverridableOrImplementable() - } + VirtualEventAccess() { targetIsOverridableOrImplementable() } } /** @@ -753,9 +697,7 @@ class VirtualEventAccess extends EventAccess { * Note that a callable access is *not* the same as a call. */ class CallableAccess extends Access, @method_access_expr { - override Callable getTarget() { - expr_access(this, result) - } + override Callable getTarget() { expr_access(this, result) } } /** @@ -774,17 +716,11 @@ class CallableAccess extends Access, @method_access_expr { * Note that a method access is *not* the same as a method call (`MethodCall`). */ class MethodAccess extends MemberAccess, CallableAccess { - MethodAccess() { - expr_access(this, any(Method m)) - } + MethodAccess() { expr_access(this, any(Method m)) } - override Method getTarget() { - expr_access(this, result) - } + override Method getTarget() { expr_access(this, result) } - override string toString() { - result = "access to method " + this.getTarget().getName() - } + override string toString() { result = "access to method " + this.getTarget().getName() } } /** @@ -803,17 +739,11 @@ class MethodAccess extends MemberAccess, CallableAccess { * (`LocalFunctionCall`). */ class LocalFunctionAccess extends CallableAccess { - LocalFunctionAccess() { - expr_access(this, any(LocalFunction f)) - } + LocalFunctionAccess() { expr_access(this, any(LocalFunction f)) } - override LocalFunction getTarget() { - expr_access(this, result) - } + override LocalFunction getTarget() { expr_access(this, result) } - override string toString() { - result = "access to local function " + this.getTarget().getName() - } + override string toString() { result = "access to local function " + this.getTarget().getName() } } /** @@ -833,9 +763,7 @@ class LocalFunctionAccess extends CallableAccess { * ``` */ class VirtualMethodAccess extends MethodAccess { - VirtualMethodAccess() { - targetIsOverridableOrImplementable() - } + VirtualMethodAccess() { targetIsOverridableOrImplementable() } } /** @@ -852,9 +780,7 @@ class VirtualMethodAccess extends MethodAccess { class TypeAccess extends MemberAccess, @type_access_expr { override Type getTarget() { result = this.getType() } - override string toString() { - result = "access to type " + this.getTarget().getName() - } + override string toString() { result = "access to type " + this.getTarget().getName() } } /** diff --git a/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll index 5fcb43a1897..38033b9a955 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll @@ -3,6 +3,7 @@ * * All arithmetic operations have the common base class `ArithmeticOperation`. */ + import Expr /** @@ -71,14 +72,14 @@ class PreDecrExpr extends DecrementOperation, @pre_decr_expr { } * A postfix increment operation, for example `x++`. */ class PostIncrExpr extends IncrementOperation, @post_incr_expr { - override string toString() { result = "..." + this.getOperator() } + override string toString() { result = "..." + this.getOperator() } } /** * A postfix decrement operation, for example `x--`. */ class PostDecrExpr extends DecrementOperation, @post_decr_expr { - override string toString() { result = "..." + this.getOperator() } + override string toString() { result = "..." + this.getOperator() } } /** @@ -131,4 +132,3 @@ class DivExpr extends BinaryArithmeticOperation, @div_expr { class RemExpr extends BinaryArithmeticOperation, @rem_expr { override string getOperator() { result = "%" } } - diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll b/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll index 92f9ceeabe3..0473a0820ff 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll @@ -13,7 +13,8 @@ import Expr */ class Assignment extends Operation, @assign_expr { Assignment() { - this instanceof LocalVariableDeclExpr implies + this instanceof LocalVariableDeclExpr + implies // Same as `this.(LocalVariableDeclExpr).hasInitializer()` but avoids // negative recursion expr_parent(_, 0, this) @@ -37,17 +38,11 @@ class Assignment extends Operation, @assign_expr { class LocalVariableDeclAndInitExpr extends LocalVariableDeclExpr, Assignment { override string getOperator() { result = "=" } - override LocalVariable getTargetVariable() { - result = getVariable() - } + override LocalVariable getTargetVariable() { result = getVariable() } - override LocalVariableAccess getLValue() { - result = Assignment.super.getLValue() - } + override LocalVariableAccess getLValue() { result = Assignment.super.getLValue() } - override string toString() { - result = LocalVariableDeclExpr.super.toString() + " = ..." - } + override string toString() { result = LocalVariableDeclExpr.super.toString() + " = ..." } } /** @@ -76,9 +71,7 @@ class AssignOperation extends Assignment, @assign_op_expr { * If an expanded version exists, then it is used in the control * flow graph. */ - AssignExpr getExpandedAssignment() { - expr_parent(result, 2, this) - } + AssignExpr getExpandedAssignment() { expr_parent(result, 2, this) } /** * Holds if this assignment operation has an expanded version. @@ -89,9 +82,7 @@ class AssignOperation extends Assignment, @assign_op_expr { * If an expanded version exists, then it is used in the control * flow graph. */ - predicate hasExpandedAssignment() { - exists(getExpandedAssignment()) - } + predicate hasExpandedAssignment() { exists(getExpandedAssignment()) } override string toString() { result = "... " + this.getOperator() + " ..." } } @@ -140,7 +131,6 @@ class AssignRemExpr extends AssignArithmeticOperation, @assign_rem_expr { override string getOperator() { result = "%=" } } - /** * A bitwise assignment operation. Either a bitwise-and assignment * operation (`AssignAndExpr`), a bitwise-or assignment @@ -149,8 +139,7 @@ class AssignRemExpr extends AssignArithmeticOperation, @assign_rem_expr { * operation (`AssignLShiftExpr`), or a right-shift assignment * operation (`AssignRShiftExpr`). */ -class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { -} +class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { } /** * A bitwise-and assignment operation, for example `x &= y`. @@ -162,7 +151,7 @@ class AssignAndExpr extends AssignBitwiseOperation, @assign_and_expr { /** * A bitwise-or assignment operation, for example `x |= y`. */ -class AssignOrExpr extends AssignBitwiseOperation, @assign_or_expr { +class AssignOrExpr extends AssignBitwiseOperation, @assign_or_expr { override string getOperator() { result = "|=" } } @@ -176,14 +165,14 @@ class AssignXorExpr extends AssignBitwiseOperation, @assign_xor_expr { /** * A left-shift assignment operation, for example `x <<= y`. */ -class AssignLShiftExpr extends AssignBitwiseOperation, @assign_lshift_expr { +class AssignLShiftExpr extends AssignBitwiseOperation, @assign_lshift_expr { override string getOperator() { result = "<<=" } } /** * A right-shift assignment operation, for example `x >>= y`. */ -class AssignRShiftExpr extends AssignBitwiseOperation, @assign_rshift_expr { +class AssignRShiftExpr extends AssignBitwiseOperation, @assign_rshift_expr { override string getOperator() { result = ">>=" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll index 465bb70d908..c96738b6961 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll @@ -3,6 +3,7 @@ * * All bitwise operations have the common base class `BitwiseOperation`. */ + import Expr /** diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll index 98247d63f33..a51451b9eb4 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll @@ -3,6 +3,7 @@ * * All calls have the common base class `Call`. */ + import Expr import semmle.code.csharp.Callable import semmle.code.csharp.dataflow.CallContext as CallContext @@ -40,27 +41,17 @@ class Call extends DotNet::Call, Expr, @call { */ override Callable getTarget() { none() } - override Expr getArgument(int i) { - result = this.getChild(i) and i >= 0 - } + override Expr getArgument(int i) { result = this.getChild(i) and i >= 0 } - override Expr getRawArgument(int i) { - result = this.getArgument(i) - } + override Expr getRawArgument(int i) { result = this.getArgument(i) } - override Expr getAnArgument() { - result = getArgument(_) - } + override Expr getAnArgument() { result = getArgument(_) } /** Gets the number of arguments of this call. */ - int getNumberOfArguments() { - result = count(this.getAnArgument()) - } + int getNumberOfArguments() { result = count(this.getAnArgument()) } /** Holds if this call has no arguments. */ - predicate hasNoArguments() { - not exists(this.getAnArgument()) - } + predicate hasNoArguments() { not exists(this.getAnArgument()) } /** * Gets the argument for this call associated with the parameter `p`, if any. @@ -86,8 +77,7 @@ class Call extends DotNet::Call, Expr, @call { * ``` */ override Expr getArgumentForParameter(DotNet::Parameter p) { - getTarget().getAParameter() = p - and + getTarget().getAParameter() = p and ( // Appears in the positional part of the call result = this.getImplicitArgument(p.getPosition()) and @@ -111,20 +101,21 @@ class Call extends DotNet::Call, Expr, @call { * of the targeted callable. */ private predicate hasMultipleParamsArguments() { - exists(Parameter p | - p = this.getTarget().getAParameter() | + exists(Parameter p | p = this.getTarget().getAParameter() | p.isParams() and exists(this.getArgument(any(int i | i > p.getPosition()))) ) } - pragma [noinline] // predicate folding to get proper join-order + // predicate folding to get proper join-order + pragma[noinline] private Expr getImplicitArgument(int pos) { result = getArgument(pos) and not exists(result.getExplicitArgumentName()) } - pragma [noinline] // predicate folding to get proper join-order + // predicate folding to get proper join-order + pragma[noinline] private Expr getExplicitArgument(string name) { result = getAnArgument() and result.getExplicitArgumentName() = name @@ -248,25 +239,19 @@ class Call extends DotNet::Call, Expr, @call { * Gets an argument that corresponds to a parameter of a potential * run-time target of this call. */ - Expr getARuntimeArgument() { - result = getRuntimeArgument(_) - } + Expr getARuntimeArgument() { result = getRuntimeArgument(_) } /** * Gets the number of arguments that correspond to a parameter of a potential * run-time target of this call. */ - int getNumberOfRuntimeArguments() { - result = count(getARuntimeArgument()) - } + int getNumberOfRuntimeArguments() { result = count(getARuntimeArgument()) } /** * Holds if this call has no arguments that correspond to a parameter of a * potential (run-time) target of this call. */ - predicate hasNoRuntimeArguments() { - not exists(getARuntimeArgument()) - } + predicate hasNoRuntimeArguments() { not exists(getARuntimeArgument()) } override string toString() { result = "call" } } @@ -307,21 +292,18 @@ private predicate isValidExplicitParamsType(Parameter p, Type t) { * ``` */ class MethodCall extends Call, QualifiableExpr, LateBindableExpr, @method_invocation_expr { - override Method getTarget() { - expr_call(this, result) - } + override Method getTarget() { expr_call(this, result) } - override Method getQualifiedDeclaration() { - result = getTarget() - } + override Method getQualifiedDeclaration() { result = getTarget() } - override string toString() { - result = "call to method " + this.getTarget().getName() - } + override string toString() { result = "call to method " + this.getTarget().getName() } override Expr getRawArgument(int i) { if exists(getQualifier()) - then (i=0 and result = getQualifier() or result = getArgument(i-1)) + then + i = 0 and result = getQualifier() + or + result = getArgument(i - 1) else result = getArgument(i) } } @@ -345,21 +327,13 @@ class MethodCall extends Call, QualifiableExpr, LateBindableExpr, @method_invoca * 6), in order to be properly matched with the parameter `i` on line 2. */ class ExtensionMethodCall extends MethodCall { - ExtensionMethodCall() { - this.getTarget() instanceof ExtensionMethod - } + ExtensionMethodCall() { this.getTarget() instanceof ExtensionMethod } - override TypeAccess getQualifier() { - result = this.getChildExpr(-1) - } + override TypeAccess getQualifier() { result = this.getChildExpr(-1) } override Expr getArgument(int i) { - exists(int j | - result = this.getChildExpr(j) | - if isOrdinaryStaticCall() then - (j = i and j >= 0) - else - (j = i - 1 and j >= -1) + exists(int j | result = this.getChildExpr(j) | + if isOrdinaryStaticCall() then (j = i and j >= 0) else (j = i - 1 and j >= -1) ) } @@ -401,13 +375,10 @@ class ExtensionMethodCall extends MethodCall { * ``` */ class VirtualMethodCall extends MethodCall { - VirtualMethodCall() { - not getQualifier() instanceof BaseAccess - and + not getQualifier() instanceof BaseAccess and getTarget().isOverridableOrImplementable() } - } /** @@ -427,17 +398,11 @@ class VirtualMethodCall extends MethodCall { * ``` */ class ConstructorInitializer extends Call, @constructor_init_expr { - override Constructor getTarget() { - expr_call(this, result) - } + override Constructor getTarget() { expr_call(this, result) } - override Constructor getARuntimeTarget() { - result = Call.super.getARuntimeTarget() - } + override Constructor getARuntimeTarget() { result = Call.super.getARuntimeTarget() } - override string toString() { - result = "call to constructor " + this.getTarget().getName() - } + override string toString() { result = "call to constructor " + this.getTarget().getName() } /** * Gets the constructor that this initializer call belongs to. For example, @@ -460,7 +425,7 @@ class ConstructorInitializer extends Call, @constructor_init_expr { override Expr getRawArgument(int i) { if this.getTarget().isStatic() then result = this.getArgument(i) - else result = this.getArgument(i-1) + else result = this.getArgument(i - 1) } } @@ -481,17 +446,11 @@ class ConstructorInitializer extends Call, @constructor_init_expr { * ``` */ class OperatorCall extends Call, LateBindableExpr, @operator_invocation_expr { - override Operator getTarget() { - expr_call(this, result) - } + override Operator getTarget() { expr_call(this, result) } - override Operator getARuntimeTarget() { - result = Call.super.getARuntimeTarget() - } + override Operator getARuntimeTarget() { result = Call.super.getARuntimeTarget() } - override string toString() { - result = "call to operator " + this.getTarget().getName() - } + override string toString() { result = "call to operator " + this.getTarget().getName() } } /** @@ -511,13 +470,13 @@ class OperatorCall extends Call, LateBindableExpr, @operator_invocation_expr { * ``` */ class MutatorOperatorCall extends OperatorCall { - MutatorOperatorCall() { mutator_invocation_mode(this,_) } + MutatorOperatorCall() { mutator_invocation_mode(this, _) } /** Holds if the operator is in prefix position. */ - predicate isPrefix() { mutator_invocation_mode(this,1) } + predicate isPrefix() { mutator_invocation_mode(this, 1) } /** Holds if the operator is in postfix position. */ - predicate isPostfix() { mutator_invocation_mode(this,2) } + predicate isPostfix() { mutator_invocation_mode(this, 2) } } /** @@ -548,7 +507,8 @@ class DelegateCall extends Call, @delegate_invocation_expr { or exists(AddEventSource aes, CallContext::CallContext cc2 | aes = this.getAnAddEventSource() and - result = aes.getARuntimeTarget(cc2) | + result = aes.getARuntimeTarget(cc2) + | aes = this.getAnAddEventSourceSameEnclosingCallable() and cc = cc2 or @@ -572,13 +532,9 @@ class DelegateCall extends Call, @delegate_invocation_expr { result.getExpr().getEnclosingCallable() != this.getEnclosingCallable() } - override Callable getARuntimeTarget() { - result = getARuntimeTarget(_) - } + override Callable getARuntimeTarget() { result = getARuntimeTarget(_) } - override Expr getRuntimeArgument(int i) { - result = getArgument(i) - } + override Expr getRuntimeArgument(int i) { result = getArgument(i) } /** * Gets the delegate expression of this delegate call. For example, the @@ -594,13 +550,9 @@ class DelegateCall extends Call, @delegate_invocation_expr { * } * ``` */ - Expr getDelegateExpr() { - result = this.getChild(-1) - } + Expr getDelegateExpr() { result = this.getChild(-1) } - override string toString() { - result = "delegate call" - } + override string toString() { result = "delegate call" } } /** @@ -613,9 +565,7 @@ class AccessorCall extends Call, QualifiableExpr, @call_access_expr { override Expr getArgument(int i) { none() } - override Accessor getARuntimeTarget() { - result = Call.super.getARuntimeTarget() - } + override Accessor getARuntimeTarget() { result = Call.super.getARuntimeTarget() } } /** @@ -634,8 +584,7 @@ class AccessorCall extends Call, QualifiableExpr, @call_access_expr { */ class PropertyCall extends AccessorCall, PropertyAccessExpr { override Accessor getTarget() { - exists(PropertyAccess pa, Property p | - pa = this and p = getProperty() | + exists(PropertyAccess pa, Property p | pa = this and p = getProperty() | pa instanceof AssignableRead and result = p.getGetter() or pa instanceof AssignableWrite and result = p.getSetter() @@ -647,9 +596,7 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr { result = AssignableInternal::getAccessorCallValueArgument(this) } - override string toString() { - result = PropertyAccessExpr.super.toString() - } + override string toString() { result = PropertyAccessExpr.super.toString() } } /** @@ -670,8 +617,7 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr { */ class IndexerCall extends AccessorCall, IndexerAccessExpr { override Accessor getTarget() { - exists(IndexerAccess ia, Indexer i | - ia = this and i = getIndexer() | + exists(IndexerAccess ia, Indexer i | ia = this and i = getIndexer() | ia instanceof AssignableRead and result = i.getGetter() or ia instanceof AssignableWrite and result = i.getSetter() @@ -713,7 +659,8 @@ class EventCall extends AccessorCall, EventAccessExpr { override EventAccessor getTarget() { exists(Event e, AddOrRemoveEventExpr aoree | e = getEvent() and - aoree.getLValue() = this | + aoree.getLValue() = this + | aoree instanceof AddEventExpr and result = e.getAddEventAccessor() or aoree instanceof RemoveEventExpr and result = e.getRemoveEventAccessor() @@ -728,9 +675,7 @@ class EventCall extends AccessorCall, EventAccessExpr { ) } - override string toString() { - result = EventAccessExpr.super.toString() - } + override string toString() { result = EventAccessExpr.super.toString() } } /** @@ -747,11 +692,7 @@ class EventCall extends AccessorCall, EventAccessExpr { * ``` */ class LocalFunctionCall extends Call, @local_function_invocation_expr { - override LocalFunction getTarget() { - expr_call(this, result) - } + override LocalFunction getTarget() { expr_call(this, result) } - override string toString() { - result = "call to local function " + getTarget().getName() - } + override string toString() { result = "call to local function " + getTarget().getName() } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll index b3c2174598a..9870ef8e15b 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll @@ -21,16 +21,12 @@ class EqualityOperation extends ComparisonOperation, @equality_op_expr { } /** * An equals operation, for example `x == y`. */ -class EQExpr extends EqualityOperation, @eq_expr { - override string getOperator() { result = "==" } -} +class EQExpr extends EqualityOperation, @eq_expr { override string getOperator() { result = "==" } } /** * A not-equals operation, for example `x != y`. */ -class NEExpr extends EqualityOperation, @ne_expr { - override string getOperator() { result = "!=" } -} +class NEExpr extends EqualityOperation, @ne_expr { override string getOperator() { result = "!=" } } /** * A relational operation. Either a greater-than operation (`GTExpr`), @@ -60,7 +56,9 @@ class RelationalOperation extends ComparisonOperation, @rel_op_expr { */ class GTExpr extends RelationalOperation, @gt_expr { override string getOperator() { result = ">" } + override Expr getGreaterOperand() { result = getLeftOperand() } + override Expr getLesserOperand() { result = getRightOperand() } } @@ -69,7 +67,9 @@ class GTExpr extends RelationalOperation, @gt_expr { */ class LTExpr extends RelationalOperation, @lt_expr { override string getOperator() { result = "<" } + override Expr getGreaterOperand() { result = getRightOperand() } + override Expr getLesserOperand() { result = getLeftOperand() } } @@ -78,7 +78,9 @@ class LTExpr extends RelationalOperation, @lt_expr { */ class GEExpr extends RelationalOperation, @ge_expr { override string getOperator() { result = ">=" } + override Expr getGreaterOperand() { result = getLeftOperand() } + override Expr getLesserOperand() { result = getRightOperand() } } @@ -87,6 +89,8 @@ class GEExpr extends RelationalOperation, @ge_expr { */ class LEExpr extends RelationalOperation, @le_expr { override string getOperator() { result = "<=" } + override Expr getGreaterOperand() { result = getRightOperand() } + override Expr getLesserOperand() { result = getLeftOperand() } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll index 117fd3891d6..43c3e60ddd4 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll @@ -1,6 +1,7 @@ /** * Provides expression classes for creating various types of object. */ + import Expr import semmle.code.csharp.Callable @@ -43,9 +44,7 @@ class ObjectInitializer extends ObjectOrCollectionInitializer, @object_init_expr * } * ``` */ - MemberInitializer getAMemberInitializer() { - result = getMemberInitializer(_) - } + MemberInitializer getAMemberInitializer() { result = getMemberInitializer(_) } /** * Gets the `i`th member initializer of this object initializer. For example, @@ -69,14 +68,10 @@ class ObjectInitializer extends ObjectOrCollectionInitializer, @object_init_expr } /** Gets the number of member initializers of this object initializer. */ - int getNumberOfMemberInitializers() { - result = count(this.getAMemberInitializer()) - } + int getNumberOfMemberInitializers() { result = count(this.getAMemberInitializer()) } /** Holds if this object initializer has no member initializers. */ - predicate hasNoMemberInitializers() { - not exists(this.getAMemberInitializer()) - } + predicate hasNoMemberInitializers() { not exists(this.getAMemberInitializer()) } } /** @@ -94,14 +89,10 @@ class ObjectInitializer extends ObjectOrCollectionInitializer, @object_init_expr * ``` */ class MemberInitializer extends AssignExpr { - MemberInitializer() { - this.getParent() instanceof ObjectInitializer - } + MemberInitializer() { this.getParent() instanceof ObjectInitializer } /** Gets the initialized member. */ - Member getInitializedMember() { - result.getAnAccess() = this.getLValue() - } + Member getInitializedMember() { result.getAnAccess() = this.getLValue() } } /** @@ -126,9 +117,7 @@ class CollectionInitializer extends ObjectOrCollectionInitializer, @collection_i * }; * ``` */ - ElementInitializer getAnElementInitializer() { - result = getElementInitializer(_) - } + ElementInitializer getAnElementInitializer() { result = getElementInitializer(_) } /** * Gets the `i`th element initializer of this collection initializer, for @@ -148,14 +137,10 @@ class CollectionInitializer extends ObjectOrCollectionInitializer, @collection_i } /** Gets the number of element initializers of this collection initializer. */ - int getNumberOfElementInitializers() { - result = count(this.getAnElementInitializer()) - } + int getNumberOfElementInitializers() { result = count(this.getAnElementInitializer()) } /** Holds if this collection initializer has no element initializers. */ - predicate hasNoElementInitializers() { - not exists(this.getAnElementInitializer()) - } + predicate hasNoElementInitializers() { not exists(this.getAnElementInitializer()) } } /** @@ -190,9 +175,7 @@ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr { override Constructor getTarget() { expr_call(this, result) } - override Constructor getARuntimeTarget() { - result = Call.super.getARuntimeTarget() - } + override Constructor getARuntimeTarget() { result = Call.super.getARuntimeTarget() } /** * Holds if this constructor call includes an object initializer or an @@ -213,14 +196,12 @@ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr { */ ObjectOrCollectionInitializer getInitializer() { result = this.getChild(-1) } - override string toString() { - result = "object creation of type " + this.getType().getName() - } + override string toString() { result = "object creation of type " + this.getType().getName() } override Expr getRawArgument(int i) { if this.getTarget().isStatic() then result = this.getArgument(i) - else result = this.getArgument(i-1) + else result = this.getArgument(i - 1) } } @@ -236,13 +217,9 @@ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr { * ``` */ class AnonymousObjectCreation extends ObjectCreation { - AnonymousObjectCreation() { - this.getObjectType() instanceof AnonymousClass - } + AnonymousObjectCreation() { this.getObjectType() instanceof AnonymousClass } - override ObjectInitializer getInitializer() { - result = this.getChild(-1) - } + override ObjectInitializer getInitializer() { result = this.getChild(-1) } } /** @@ -252,9 +229,7 @@ class AnonymousObjectCreation extends ObjectCreation { */ class DelegateCreation extends Expr, @delegate_creation_expr { /** Gets the delegate type of this delegate creation. */ - DelegateType getDelegateType() { - result = this.getType() - } + DelegateType getDelegateType() { result = this.getType() } /** * Gets the argument of this delegate creation. Either a callable access @@ -263,9 +238,7 @@ class DelegateCreation extends Expr, @delegate_creation_expr { */ Expr getArgument() { result = this.getAChild() } - override string toString() { - result = "delegate creation of type " + this.getType().getName() - } + override string toString() { result = "delegate creation of type " + this.getType().getName() } } /** @@ -322,9 +295,7 @@ class ArrayInitializer extends Expr, @array_init_expr { * }; * ``` */ - Expr getAnElement() { - result = getElement(_) - } + Expr getAnElement() { result = getElement(_) } /** * Gets the `i`th element of this array initializer, for example the second @@ -344,9 +315,7 @@ class ArrayInitializer extends Expr, @array_init_expr { } /** Gets the number of elements in this array initializer. */ - int getNumberOfElements() { - result = count(this.getAnElement()) - } + int getNumberOfElements() { result = count(this.getAnElement()) } /** Holds if this array initializer has no elements. */ predicate hasNoElements() { not exists(this.getAnElement()) } @@ -369,9 +338,7 @@ class ArrayCreation extends Expr, @array_creation_expr { * new int[5, 10] * ``` */ - Expr getALengthArgument() { - result = getLengthArgument(_) - } + Expr getALengthArgument() { result = getLengthArgument(_) } /** * Gets the `i`th dimension's length argument of this array creation, for @@ -387,9 +354,7 @@ class ArrayCreation extends Expr, @array_creation_expr { } /** Gets the number of length arguments of this array creation. */ - int getNumberOfLengthArguments() { - result = count(this.getALengthArgument()) - } + int getNumberOfLengthArguments() { result = count(this.getALengthArgument()) } /** Holds if the created array is implicitly sized by the initializer. */ predicate isImplicitlySized() { not explicitly_sized_array_creation(this) } @@ -403,9 +368,7 @@ class ArrayCreation extends Expr, @array_creation_expr { /** Holds if the type of the created array is inferred from its initializer. */ predicate isImplicitlyTyped() { implicitly_typed_array_creation(this) } - override string toString() { - result = "array creation of type " + this.getType().getName() - } + override string toString() { result = "array creation of type " + this.getType().getName() } } /** @@ -415,9 +378,7 @@ class ArrayCreation extends Expr, @array_creation_expr { class AnonymousFunctionExpr extends Expr, Callable, @anonymous_function_expr { override string getName() { result = "" } - override Type getReturnType() { - result = getType().(DelegateType).getReturnType() - } + override Type getReturnType() { result = getType().(DelegateType).getReturnType() } override AnonymousFunctionExpr getSourceDeclaration() { result = this } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll b/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll index e6d75471961..fbc9915ca23 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll @@ -14,11 +14,7 @@ private import semmle.code.csharp.dispatch.Dispatch * dynamic member access (`DynamicMemberAccess`), a dynamic accessor call * (`DynamicAccessorCall`), or a dynamic element access (`DynamicElementAccess`). */ -class DynamicExpr extends LateBindableExpr { - DynamicExpr() { - isLateBound() - } -} +class DynamicExpr extends LateBindableExpr { DynamicExpr() { isLateBound() } } /** * A constructor call where one of the arguments is a `dynamic` expression, for @@ -67,9 +63,7 @@ class DynamicObjectCreation extends DynamicExpr, ObjectCreation { * may not be known at compile-time (as in the example above). */ class DynamicMethodCall extends DynamicExpr, MethodCall { - override string toString() { - result = "dynamic call to method " + getLateBoundTargetName() - } + override string toString() { result = "dynamic call to method " + getLateBoundTargetName() } } /** @@ -97,9 +91,7 @@ class DynamicMethodCall extends DynamicExpr, MethodCall { * target operator may not be known at compile-time (as in the example above). */ class DynamicOperatorCall extends DynamicExpr, OperatorCall { - override string toString() { - result = "dynamic call to operator " + getLateBoundTargetName() - } + override string toString() { result = "dynamic call to operator " + getLateBoundTargetName() } } /** @@ -187,10 +179,9 @@ class DynamicAccess extends DynamicExpr { * of the member being accessed may not be known (it can be either a field, a * property, or an event). */ -class DynamicMemberAccess extends DynamicAccess, MemberAccess, AssignableAccess, @dynamic_member_access_expr { - override string toString() { - result = "dynamic access to member " + getLateBoundTargetName() - } +class DynamicMemberAccess extends DynamicAccess, MemberAccess, AssignableAccess, + @dynamic_member_access_expr { + override string toString() { result = "dynamic access to member " + getLateBoundTargetName() } // The target is unknown when the qualifier is a `dynamic` expression override DynamicMember getTarget() { none() } @@ -303,10 +294,7 @@ class DynamicAccessorCall extends DynamicAccess { Accessor target; DynamicAccessorCall() { - exists(DispatchCall dc | - dc.getCall() = this | - target = dc.getADynamicTarget() - ) + exists(DispatchCall dc | dc.getCall() = this | target = dc.getADynamicTarget()) } /** Gets an actual run-time target of this dynamic accessor call. */ diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index 6c2b720dc96..22e600513ed 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -47,20 +47,16 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr { override Type getType() { expressions(this, _, getTypeRef(result)) } /** Gets the value of this expression, if any */ - override string getValue() { expr_value(this,result) } + override string getValue() { expr_value(this, result) } /** Holds if this expression has a value. */ predicate hasValue() { exists(getValue()) } /** Gets the enclosing statement of this expression, if any. */ - final Stmt getEnclosingStmt() { - enclosingStmt(this, result) - } + final Stmt getEnclosingStmt() { enclosingStmt(this, result) } /** Gets the enclosing callable of this expression, if any. */ - override Callable getEnclosingCallable() { - exprEnclosingCallable(this, result) - } + override Callable getEnclosingCallable() { exprEnclosingCallable(this, result) } /** * Holds if this expression is generated by the compiler and does not appear @@ -87,9 +83,7 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr { * argument for, if any. For example, if this expression is `0` in * `M(second: 1, first: 0)` then the result is `"first"`. */ - string getExplicitArgumentName() { - expr_argument_name(this, result) - } + string getExplicitArgumentName() { expr_argument_name(this, result) } override Element getParent() { result = ControlFlowElement.super.getParent() } } @@ -110,9 +104,7 @@ class LateBindableExpr extends Expr, @late_bindable_expr { } /** Gets the name of the target that is late bound, if any. */ - string getLateBoundTargetName() { - dynamic_member_name(this, result) - } + string getLateBoundTargetName() { dynamic_member_name(this, result) } } private predicate isDynamicMemberAccess(@dynamic_member_access_expr e) { any() } @@ -124,7 +116,7 @@ private predicate isDynamicElementAccess(@dynamic_element_access_expr e) { any() */ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr { /** Gets the local variable being declared. */ - LocalVariable getVariable() { localvars(result,_,_,_,_,this) } + LocalVariable getVariable() { localvars(result, _, _, _, _, this) } /** Gets the name of the variable being declared. */ string getName() { result = this.getVariable().getName() } @@ -155,22 +147,16 @@ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr { * Holds if this variable declaration is defined as an `out` argument, * for example `M(out int x)`. */ - predicate isOutArgument() { - expr_argument(this, 2) - } + predicate isOutArgument() { expr_argument(this, 2) } } /** * A local constant declaration, for example `const int i = 0`. */ class LocalConstantDeclExpr extends LocalVariableDeclExpr { - LocalConstantDeclExpr() { - super.getVariable() instanceof LocalConstant - } + LocalConstantDeclExpr() { super.getVariable() instanceof LocalConstant } - override LocalConstant getVariable() { - localvars(result,_,_,_,_,this) - } + override LocalConstant getVariable() { localvars(result, _, _, _, _, this) } } /** @@ -281,9 +267,9 @@ class IsExpr extends Expr, @is_expr { /** * An `is` type expression, for example, `x is string` or `x is string s`. */ -class IsTypeExpr extends IsExpr -{ +class IsTypeExpr extends IsExpr { TypeAccess typeAccess; + IsTypeExpr() { typeAccess = this.getChild(1) } /** @@ -302,9 +288,9 @@ class IsTypeExpr extends IsExpr /** * An `is` pattern expression, for example `x is string s`. */ -class IsPatternExpr extends IsTypeExpr -{ +class IsPatternExpr extends IsTypeExpr { LocalVariableDeclExpr typeDecl; + IsPatternExpr() { typeDecl = this.getChild(2) } /** @@ -317,9 +303,9 @@ class IsPatternExpr extends IsTypeExpr /** * An `is` constant expression, for example `x is 5`. */ -class IsConstantExpr extends IsExpr -{ +class IsConstantExpr extends IsExpr { Expr constant; + IsConstantExpr() { constant = this.getChild(3) } /** Gets the constant expression, for example `5` in `x is 5`. */ @@ -353,10 +339,7 @@ class Cast extends Expr { override Expr stripCasts() { result = this.getExpr().stripCasts() } override Expr stripImplicitCasts() { - if this.isImplicit() then - result = this.getExpr().stripImplicitCasts() - else - result = this + if this.isImplicit() then result = this.getExpr().stripImplicitCasts() else result = this } } @@ -371,11 +354,7 @@ class Cast extends Expr { * } * ``` */ -class ImplicitCast extends Cast { - ImplicitCast() { - this.isImplicit() - } -} +class ImplicitCast extends Cast { ImplicitCast() { this.isImplicit() } } /** * An explicit cast. For example, the explicit cast from `object` to `string` @@ -387,25 +366,17 @@ class ImplicitCast extends Cast { * } * ``` */ -class ExplicitCast extends Cast { - ExplicitCast() { - not this instanceof ImplicitCast - } -} +class ExplicitCast extends Cast { ExplicitCast() { not this instanceof ImplicitCast } } /** * An `as` expression, for example `x as string`. */ -class AsExpr extends Cast, @as_expr { - override string toString() { result = "... as ..." } -} +class AsExpr extends Cast, @as_expr { override string toString() { result = "... as ..." } } /** * A cast expression, for example `(string) x`. */ -class CastExpr extends Cast, @cast_expr { - override string toString() { result = "(...) ..." } -} +class CastExpr extends Cast, @cast_expr { override string toString() { result = "(...) ..." } } /** * A `typeof` expression, for example `typeof(string)`. @@ -431,9 +402,7 @@ class DefaultValueExpr extends Expr, @default_expr { TypeAccess getTypeAccess() { result = this.getChild(0) } override string toString() { - if exists(getTypeAccess()) - then result = "default(...)" - else result = "default" + if exists(getTypeAccess()) then result = "default(...)" else result = "default" } } @@ -449,9 +418,7 @@ class SizeofExpr extends UnaryOperation, @sizeof_expr { override string getOperator() { result = "sizeof(..)" } - override string toString() { - result = "sizeof(..)" - } + override string toString() { result = "sizeof(..)" } } /** @@ -514,13 +481,9 @@ class AddressOfExpr extends UnaryOperation, @address_of_expr { */ class AwaitExpr extends Expr, @await_expr { /** Gets the expression being awaited. */ - Expr getExpr() { - result = getChild(0) - } + Expr getExpr() { result = getChild(0) } - override string toString() { - result = "await ..." - } + override string toString() { result = "await ..." } } /** @@ -535,17 +498,13 @@ class AwaitExpr extends Expr, @await_expr { * ``` */ class NameOfExpr extends Expr, @nameof_expr { - override string toString() { - result = "nameof(...)" - } + override string toString() { result = "nameof(...)" } /** * Gets the access in this `nameof` expression, for example `x.F` in * `nameof(x.F)`. */ - Access getAccess() { - result = this.getChild(0) - } + Access getAccess() { result = this.getChild(0) } } /** @@ -558,9 +517,7 @@ class NameOfExpr extends Expr, @nameof_expr { * ``` */ class InterpolatedStringExpr extends Expr, @interpolated_string_expr { - override string toString() { - result = "$\"...\"" - } + override string toString() { result = "$\"...\"" } /** * Gets the insert at index `i` in this interpolated string, if any. For @@ -579,19 +536,13 @@ class InterpolatedStringExpr extends Expr, @interpolated_string_expr { * `$"Hello, {name}!"`. Note that there is no text element at index `i = 1`, * but instead an insert (`getInsert(1)` gets the insert). */ - StringLiteral getText(int i) { - result = getChild(i) - } + StringLiteral getText(int i) { result = getChild(i) } /** Gets an insert in this interpolated string. */ - Expr getAnInsert() { - result = getInsert(_) - } + Expr getAnInsert() { result = getInsert(_) } /** Gets a text element in this interpolated string. */ - StringLiteral getAText() { - result = getText(_) - } + StringLiteral getAText() { result = getText(_) } } /** @@ -621,9 +572,7 @@ class ThrowElement extends ControlFlowElement, DotNet::Throw, @throw_element { * `return i != 0 ? 1 / i : throw new ArgumentException("i");` */ class ThrowExpr extends Expr, ThrowElement, @throw_expr { - override string toString() { - result = "throw ..." - } + override string toString() { result = "throw ..." } /** * Gets the expression of the exception being thrown. @@ -655,9 +604,7 @@ class QualifiableExpr extends Expr, @qualifiable_expr { final predicate hasQualifier() { exists(getQualifier()) } /** Holds if this expression has an implicit `this` qualifier. */ - predicate hasImplicitThisQualifier() { - this.getQualifier().(ThisAccess).isImplicit() - } + predicate hasImplicitThisQualifier() { this.getQualifier().(ThisAccess).isImplicit() } /** Holds if this call has an implicit or explicit `this` qualifier. */ predicate hasThisQualifier() { @@ -691,15 +638,12 @@ class QualifiableExpr extends Expr, @qualifiable_expr { * Holds if the target of this expression can be overridden or implemented. */ predicate targetIsOverridableOrImplementable() { - not this.getQualifier() instanceof BaseAccess - and + not this.getQualifier() instanceof BaseAccess and this.getQualifiedDeclaration().(Virtualizable).isOverridableOrImplementable() } /** Holds if this expression has a conditional qualifier `?.` */ - predicate isConditional() { - conditional_access(this) - } + predicate isConditional() { conditional_access(this) } } /** @@ -717,22 +661,16 @@ class QualifiableExpr extends Expr, @qualifiable_expr { * ``` */ class TupleExpr extends Expr, @tuple_expr { - override string toString() { result="(..., ...)" } + override string toString() { result = "(..., ...)" } /** Gets the `i`th argument of this tuple. */ - Expr getArgument(int i) { - result = getChild(i) - } + Expr getArgument(int i) { result = getChild(i) } /** Gets an argument of this tuple. */ - Expr getAnArgument() { - result = getArgument(_) - } + Expr getAnArgument() { result = getArgument(_) } /** Holds if this tuple is a read access. */ - predicate isReadAccess() { - not exists(AssignExpr e | this = e.getLValue().getAChildExpr*()) - } + predicate isReadAccess() { not exists(AssignExpr e | this = e.getLValue().getAChildExpr*()) } } /** @@ -745,19 +683,12 @@ class TupleExpr extends Expr, @tuple_expr { * ``` */ class RefExpr extends Expr, @ref_expr { - /** Gets the expression being referenced. */ - Expr getExpr() { - result = getChild(0) - } + Expr getExpr() { result = getChild(0) } - override string toString() { - result = "ref ..." - } + override string toString() { result = "ref ..." } - override Type getType() { - result = getExpr().getType() - } + override Type getType() { result = getExpr().getType() } } /** @@ -767,6 +698,4 @@ class RefExpr extends Expr, @ref_expr { * (var name, _, _) = GetDetails(); * ``` */ -class DiscardExpr extends Expr, @discard_expr { - override string toString() { result="_" } -} +class DiscardExpr extends Expr, @discard_expr { override string toString() { result = "_" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll b/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll index 6bb51c3a722..671a4044a8b 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll @@ -15,6 +15,7 @@ private import dotnet */ class Literal extends DotNet::Literal, Expr, @literal_expr { override string toString() { result = this.getValue() } + override string getValue() { result = Expr.super.getValue() } } @@ -88,8 +89,7 @@ class DecimalLiteral extends RealLiteral, @decimal_literal_expr { } * A `string` literal, for example `"Hello, World!"`. */ class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr { - override string toString() { - result = "\"" + getValue().replaceAll("\"", "\\\"") + "\"" } + override string toString() { result = "\"" + getValue().replaceAll("\"", "\\\"") + "\"" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll index f4386c8c275..b7240a0e9b2 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll @@ -3,6 +3,7 @@ * * All logical operations have the common base class `LogicalOperation`. */ + import Expr /** @@ -10,9 +11,7 @@ import Expr * a binary logical operation (`BinaryLogicalOperation`), or a ternary logical * operation (`TernaryLogicalOperation`). */ -class LogicalOperation extends Operation, @log_expr { - override string getOperator() { none() } -} +class LogicalOperation extends Operation, @log_expr { override string getOperator() { none() } } /** * A unary logical operation, that is, a logical 'not' (`LogicalNotExpr`). @@ -31,7 +30,7 @@ class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr { * a logical 'or' (`LogicalAndExpr`), or a null-coalescing operation * (`NullCoalescingExpr`). */ -class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr{ +class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log_op_expr { override string getOperator() { none() } } @@ -66,7 +65,7 @@ class NullCoalescingExpr extends BinaryLogicalOperation, @null_coalescing_expr { * A ternary logical operation, that is, a ternary conditional expression * (`ConditionalExpr`). */ -class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_op_expr{ } +class TernaryLogicalOperation extends LogicalOperation, TernaryOperation, @ternary_log_op_expr { } /** * A conditional expression, for example `s != null ? s.Length : -1` @@ -83,12 +82,12 @@ class ConditionalExpr extends TernaryLogicalOperation, @conditional_expr { Expr getCondition() { result = this.getChild(0) } /** Gets the "then" expression of this conditional expression. */ - Expr getThen() {result = this.getChild(1) } + Expr getThen() { result = this.getChild(1) } /** Gets the "else" expression of this conditional expression. */ Expr getElse() { result = this.getChild(2) } override string getOperator() { result = "?" } - override string toString() { result = "... ? ... : ..." } + override string toString() { result = "... ? ... : ..." } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll index ec9d745918c..21b0e2938de 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Format.qll @@ -9,8 +9,7 @@ private import semmle.code.csharp.frameworks.system.Text /** A method that formats a string, for example `string.Format()`. */ class FormatMethod extends Method { FormatMethod() { - exists(Class declType | - declType = this.getDeclaringType() | + exists(Class declType | declType = this.getDeclaringType() | this.getParameter(0).getType() instanceof SystemIFormatProviderInterface and this.getParameter(1).getType() instanceof StringType and this.getNumberOfParameters() >= 3 and @@ -27,20 +26,22 @@ class FormatMethod extends Method { or this = any(SystemTextStringBuilderClass c).getAppendFormatMethod() or + (this.hasName("Write") or this.hasName("WriteLine")) and ( - (this.hasName("Write") or this.hasName("WriteLine")) and - ( - declType.hasQualifiedName("System.Console") - or - declType.hasQualifiedName("System.IO.TextWriter") - or - declType.hasQualifiedName("System.Diagnostics.Debug") and - this.getParameter(1).getType() instanceof ArrayType - ) + declType.hasQualifiedName("System.Console") + or + declType.hasQualifiedName("System.IO.TextWriter") + or + declType.hasQualifiedName("System.Diagnostics.Debug") and + this.getParameter(1).getType() instanceof ArrayType ) or declType.hasQualifiedName("System.Diagnostics.Trace") and - (this.hasName("TraceError") or this.hasName("TraceInformation") or this.hasName("TraceWarning")) + ( + this.hasName("TraceError") or + this.hasName("TraceInformation") or + this.hasName("TraceWarning") + ) or this.hasName("TraceInformation") and declType.hasQualifiedName("System.Diagnostics.TraceSource") @@ -60,13 +61,14 @@ class FormatMethod extends Method { * `string.Format(IFormatProvider, String, Object)` is `1`. */ int getFormatArgument() { - if this.getParameter(0).getType() instanceof SystemIFormatProviderInterface then - result = 1 + if this.getParameter(0).getType() instanceof SystemIFormatProviderInterface + then result = 1 else - if this.hasName("Assert") and this.getDeclaringType().hasQualifiedName("System.Diagnostics.Debug") then - result = 2 - else - result = 0 + if + this.hasName("Assert") and + this.getDeclaringType().hasQualifiedName("System.Diagnostics.Debug") + then result = 2 + else result = 0 } } @@ -78,14 +80,16 @@ class FormatMethod extends Method { class StringFormatItemParameter extends Parameter { StringFormatItemParameter() { // Parameter of a format method - exists(FormatMethod m, int pos | - m = this.getCallable() | + exists(FormatMethod m, int pos | m = this.getCallable() | pos = this.getPosition() and pos > m.getFormatArgument() ) or // Parameter of a source method that forwards to `string.Format()` - exists(AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr, StringFormatItemParameter other | + exists( + AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr, + StringFormatItemParameter other + | def.getParameter() = this and pr = def.getAReachableRead() and pr.getAControlFlowNode().postDominates(this.getCallable().getEntryPoint()) and @@ -96,16 +100,11 @@ class StringFormatItemParameter extends Parameter { } private Type getParameterType(Parameter p) { - if p.isParams() then - result = p.getType().(ArrayType).getElementType() - else - result = p.getType() + if p.isParams() then result = p.getType().(ArrayType).getElementType() else result = p.getType() } /** Regex for a valid insert. */ -private string getFormatInsertRegex() { - result = "\\{(\\d+)\\s*(,\\s*-?\\d+\\s*)?(:[^{}]+)?\\}" -} +private string getFormatInsertRegex() { result = "\\{(\\d+)\\s*(,\\s*-?\\d+\\s*)?(:[^{}]+)?\\}" } /** * Regex for a valid token in the string. @@ -113,35 +112,28 @@ private string getFormatInsertRegex() { * Note that the format string can be tokenised using this regex. */ private string getValidFormatTokenRegex() { - result="[^{}]|\\{\\{|\\}\\}|" + getFormatInsertRegex() + result = "[^{}]|\\{\\{|\\}\\}|" + getFormatInsertRegex() } /** Regex for the entire format string */ -private string getValidFormatRegex() { - result = "(" + getValidFormatTokenRegex() + ")*+" -} +private string getValidFormatRegex() { result = "(" + getValidFormatTokenRegex() + ")*+" } /** A literal with a valid format string. */ class ValidFormatString extends StringLiteral { - ValidFormatString() { - this.getValue().regexpMatch(getValidFormatRegex()) - } + ValidFormatString() { this.getValue().regexpMatch(getValidFormatRegex()) } /** Gets the token at the given position in the string. */ string getToken(int outPosition) { result = this.getValue().regexpFind(getValidFormatTokenRegex(), _, outPosition) } - - /**Gets the insert number at the given position in the string.*/ + /**Gets the insert number at the given position in the string. */ int getInsert(int position) { result = this.getToken(position).regexpCapture(getFormatInsertRegex(), 1).toInt() } - /** Gets any insert number in the string.*/ - int getAnInsert(){ - result = this.getInsert(_) - } + /** Gets any insert number in the string. */ + int getAnInsert() { result = this.getInsert(_) } } /** @@ -150,20 +142,22 @@ class ValidFormatString extends StringLiteral { * Such a literal would cause `string.Format()` to throw an exception. */ class InvalidFormatString extends StringLiteral { - InvalidFormatString() { - not this.getValue().regexpMatch(getValidFormatRegex()) - } + InvalidFormatString() { not this.getValue().regexpMatch(getValidFormatRegex()) } /** Gets the offset of the first error. */ int getInvalidOffset() { - result = this.getValue().regexpFind(getValidFormatRegex(),0,0).length() + result = this.getValue().regexpFind(getValidFormatRegex(), 0, 0).length() } override string getURL() { - exists(string filepath, int startline, int startcolumn, int endline, int endcolumn, int oldstartcolumn, int padding | + exists( + string filepath, int startline, int startcolumn, int endline, int endcolumn, + int oldstartcolumn, int padding + | this.getLocation().hasLocationInfo(filepath, startline, oldstartcolumn, endline, endcolumn) and startcolumn = padding + oldstartcolumn + getInvalidOffset() and - toUrl(filepath, startline, startcolumn, endline, endcolumn, result) | + toUrl(filepath, startline, startcolumn, endline, endcolumn, result) + | // Single-line string literal beginning " or @" // Figure out the correct indent. startline = endline and @@ -183,9 +177,7 @@ private module FormatFlow { private class FormatConfiguration extends DataFlow::Configuration { FormatConfiguration() { this = "format" } - override predicate isSource(DataFlow::Node n) { - n.asExpr() instanceof StringLiteral - } + override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLiteral } override predicate isSink(DataFlow::Node n) { exists(FormatCall c | n.asExpr() = c.getFormatExpr()) @@ -194,7 +186,8 @@ private module FormatFlow { predicate hasFlow(StringLiteral lit, Expr format) { exists(DataFlow::Node n1, DataFlow::Node n2, FormatConfiguration conf | - n1.asExpr() = lit and n2.asExpr() = format | + n1.asExpr() = lit and n2.asExpr() = format + | conf.hasFlow(n1, n2) ) } @@ -205,24 +198,16 @@ private module FormatFlow { * to `string.Format()`. */ class FormatCall extends MethodCall { - FormatCall() { - this.getTarget() instanceof FormatMethod - } + FormatCall() { this.getTarget() instanceof FormatMethod } /** Gets the expression used as the format string. */ - Expr getFormatExpr() { - result = this.getArgument(this.getFormatArgument()) - } + Expr getFormatExpr() { result = this.getArgument(this.getFormatArgument()) } /** Gets the argument number containing the format string. */ - int getFormatArgument() { - result = this.getTarget().(FormatMethod).getFormatArgument() - } + int getFormatArgument() { result = this.getTarget().(FormatMethod).getFormatArgument() } /** Gets the argument number of the first supplied insert. */ - int getFirstArgument() { - result = this.getFormatArgument() + 1 - } + int getFirstArgument() { result = this.getFormatArgument() + 1 } /** Holds if the arguments are supplied in an array, not individually. */ predicate hasArrayExpr() { @@ -234,9 +219,7 @@ class FormatCall extends MethodCall { * Gets a format string. Global data flow analysis is applied to retrieve all * sources that can reach this method call. */ - StringLiteral getAFormatSource() { - FormatFlow::hasFlow(result, this.getFormatExpr()) - } + StringLiteral getAFormatSource() { FormatFlow::hasFlow(result, this.getFormatExpr()) } /** * Gets the number of supplied arguments (excluding the format string and format @@ -249,9 +232,7 @@ class FormatCall extends MethodCall { } /** Gets an index if a supplied argument. */ - int getASuppliedArgument() { - result in [0 .. this.getSuppliedArguments() - 1] - } + int getASuppliedArgument() { result in [0 .. this.getSuppliedArguments() - 1] } /** Get the expression supplied at the given position. */ Expr getSuppliedExpr(int index) { diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Microsoft.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Microsoft.qll index 4d353e219eb..261b15cd444 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Microsoft.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Microsoft.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `Microsoft`. */ + import csharp /** The `Microsoft` namespace. */ diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Moq.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Moq.qll index 1c81df356db..92811122696 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Moq.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Moq.qll @@ -1,11 +1,10 @@ /** Provides definitions related to the namespace `Moq`. */ + import csharp /** The `Moq.Language` Namespace. */ class MoqLanguageNamespace extends Namespace { - MoqLanguageNamespace() { - this.hasQualifiedName("Moq.Language") - } + MoqLanguageNamespace() { this.hasQualifiedName("Moq.Language") } } /** @@ -23,11 +22,9 @@ class ReturnsMethod extends Method { Expr getAReturnedExpr() { exists(MethodCall mc, Expr arg | mc = getACall() and - arg = mc.getArgument(0) | - if arg instanceof LambdaExpr then - arg.(LambdaExpr).canReturn(result) - else - result = arg + arg = mc.getArgument(0) + | + if arg instanceof LambdaExpr then arg.(LambdaExpr).canReturn(result) else result = arg ) } } @@ -35,8 +32,7 @@ class ReturnsMethod extends Method { /** An object creation that is returned by a mock. */ class ReturnedByMockObject extends ObjectCreation { ReturnedByMockObject() { - exists(Variable v | - this = v.getAnAssignedValue() | + exists(Variable v | this = v.getAnAssignedValue() | v.getAnAccess() = any(ReturnsMethod rm).getAReturnedExpr().getAChild*() ) } @@ -45,6 +41,6 @@ class ReturnedByMockObject extends ObjectCreation { * Gets a value used to initialize a member of this object creation. */ Expr getAMemberInitializationValue() { - result = this.getInitializer().(ObjectInitializer).getAMemberInitializer().getRValue() + result = this.getInitializer().(ObjectInitializer).getAMemberInitializer().getRValue() } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/Sql.qll b/csharp/ql/src/semmle/code/csharp/frameworks/Sql.qll index f9a2433b3c7..c0167a8fc01 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/Sql.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/Sql.qll @@ -1,4 +1,5 @@ /** Provides definitions related to SQL frameworks. */ + import csharp private import semmle.code.csharp.frameworks.system.Data private import semmle.code.csharp.frameworks.system.data.Entity @@ -15,44 +16,38 @@ class CommandTextAssignmentSqlExpr extends SqlExpr, AssignExpr { CommandTextAssignmentSqlExpr() { exists(Property p, SystemDataIDbCommandInterface i, Property text | p = this.getLValue().(PropertyAccess).getTarget() and - text = i.getCommandTextProperty() | + text = i.getCommandTextProperty() + | p.overridesOrImplementsOrEquals(text) ) } - override - Expr getSql() { result = getRValue() } + override Expr getSql() { result = getRValue() } } /** A construction of an `IDbCommand` object. */ class IDbCommandConstructionSqlExpr extends SqlExpr, ObjectCreation { IDbCommandConstructionSqlExpr() { - exists(InstanceConstructor ic | - ic = this.getTarget() | - ic.getDeclaringType().getABaseType*() instanceof SystemDataIDbCommandInterface - and + exists(InstanceConstructor ic | ic = this.getTarget() | + ic.getDeclaringType().getABaseType*() instanceof SystemDataIDbCommandInterface and ic.getParameter(0).getType() instanceof StringType ) } - override - Expr getSql() { result = getArgument(0) } + override Expr getSql() { result = getArgument(0) } } /** A construction of an `SqlDataAdapter` object. */ class SqlDataAdapterConstructionSqlExpr extends SqlExpr, ObjectCreation { SqlDataAdapterConstructionSqlExpr() { exists(InstanceConstructor ic | - ic = this.getTarget() - and - ic.getDeclaringType() instanceof SystemDataSqlClientSqlDataAdapterClass - and + ic = this.getTarget() and + ic.getDeclaringType() instanceof SystemDataSqlClientSqlDataAdapterClass and ic.getParameter(0).getType() instanceof StringType ) } - override - Expr getSql() { result = getArgument(0) } + override Expr getSql() { result = getArgument(0) } } /** A `MySql.Data.MySqlClient.MySqlHelper` method. */ @@ -61,8 +56,7 @@ class MySqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall { this.getQualifier().getType().(Class).hasQualifiedName("MySql.Data.MySqlClient", "MySqlHelper") } - override - Expr getSql() { + override Expr getSql() { exists(int i | result = getArgument(i) and this.getTarget().getParameter(i).hasName("commandText") and @@ -74,11 +68,14 @@ class MySqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall { /** A `Microsoft.ApplicationBlocks.Data.SqlHelper` method. */ class MicrosoftSqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall { MicrosoftSqlHelperMethodCallSqlExpr() { - this.getQualifier().getType().(Class).hasQualifiedName("Microsoft.ApplicationBlocks.Data", "SqlHelper") + this + .getQualifier() + .getType() + .(Class) + .hasQualifiedName("Microsoft.ApplicationBlocks.Data", "SqlHelper") } - override - Expr getSql() { + override Expr getSql() { exists(int i | result = getArgument(i) and this.getTarget().getParameter(i).hasName("commandText") and @@ -93,10 +90,7 @@ class SystemDataEntityDbSetSqlExpr extends SqlExpr, MethodCall { this.getTarget() = any(SystemDataEntity::DbSet dbSet).getSqlQueryMethod() } - override - Expr getSql() { - result = getArgumentForName("sql") - } + override Expr getSql() { result = getArgumentForName("sql") } } /** A call to a method in `System.Data.Entity.Database` that executes SQL. */ @@ -109,8 +103,5 @@ class SystemDataEntityDatabaseSqlExpr extends SqlExpr, MethodCall { ) } - override - Expr getSql() { - result = getArgumentForName("sql") - } + override Expr getSql() { result = getArgumentForName("sql") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/System.qll b/csharp/ql/src/semmle/code/csharp/frameworks/System.qll index 823fdef24e5..2ca1dbaecec 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/System.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/System.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System`. */ + import csharp private import system.Reflection @@ -11,144 +12,94 @@ class SystemNamespace extends Namespace { } /** A class in the `System` namespace. */ -class SystemClass extends Class { - SystemClass() { - this.getNamespace() instanceof SystemNamespace - } -} +class SystemClass extends Class { SystemClass() { this.getNamespace() instanceof SystemNamespace } } /** An unbound generic class in the `System` namespace. */ class SystemUnboundGenericClass extends UnboundGenericClass { - SystemUnboundGenericClass() { - this.getNamespace() instanceof SystemNamespace - } + SystemUnboundGenericClass() { this.getNamespace() instanceof SystemNamespace } } /** An interface in the `System` namespace. */ class SystemInterface extends Interface { - SystemInterface() { - this.getNamespace() instanceof SystemNamespace - } + SystemInterface() { this.getNamespace() instanceof SystemNamespace } } /** An unbound generic interface in the `System` namespace. */ class SystemUnboundGenericInterface extends UnboundGenericInterface { - SystemUnboundGenericInterface() { - this.getNamespace() instanceof SystemNamespace - } + SystemUnboundGenericInterface() { this.getNamespace() instanceof SystemNamespace } } /** A delegate type in the `System` namespace. */ class SystemDelegateType extends DelegateType { - SystemDelegateType() { - this.getNamespace() instanceof SystemNamespace - } + SystemDelegateType() { this.getNamespace() instanceof SystemNamespace } } /** An unbound generic delegate type in the `System` namespace. */ class SystemUnboundGenericDelegateType extends UnboundGenericDelegateType { - SystemUnboundGenericDelegateType() { - this.getNamespace() instanceof SystemNamespace - } + SystemUnboundGenericDelegateType() { this.getNamespace() instanceof SystemNamespace } } /** The `System.Action` delegate type. */ class SystemActionDelegateType extends SystemDelegateType { - SystemActionDelegateType() { - this.getName() = "Action" - } + SystemActionDelegateType() { this.getName() = "Action" } } /** The `System.Action` delegate type. */ class SystemActionTDelegateType extends SystemUnboundGenericDelegateType { - SystemActionTDelegateType() { - this.getName().regexpMatch("Action<,*>") - } + SystemActionTDelegateType() { this.getName().regexpMatch("Action<,*>") } } /** `System.Array` class. */ -class SystemArrayClass extends SystemClass { - SystemArrayClass() { - this.hasName("Array") - } -} +class SystemArrayClass extends SystemClass { SystemArrayClass() { this.hasName("Array") } } /** The `System.Boolean` structure. */ class SystemBooleanStruct extends BoolType { /** Gets the `Parse(string)` method. */ Method getParseMethod() { - result.getDeclaringType() = this - and - result.hasName("Parse") - and - result.getNumberOfParameters() = 1 - and - result.getParameter(0).getType() instanceof StringType - and + result.getDeclaringType() = this and + result.hasName("Parse") and + result.getNumberOfParameters() = 1 and + result.getParameter(0).getType() instanceof StringType and result.getReturnType() instanceof BoolType } /** Gets the `TryParse(string, out bool)` method. */ Method getTryParseMethod() { - result.getDeclaringType() = this - and - result.hasName("TryParse") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof StringType - and - result.getParameter(1).getType() instanceof BoolType - and + result.getDeclaringType() = this and + result.hasName("TryParse") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof StringType and + result.getParameter(1).getType() instanceof BoolType and result.getReturnType() instanceof BoolType } } /** The `System.Convert` class. */ -class SystemConvertClass extends SystemClass { - SystemConvertClass() { - this.hasName("Convert") - } -} +class SystemConvertClass extends SystemClass { SystemConvertClass() { this.hasName("Convert") } } /** `System.Delegate` class. */ -class SystemDelegateClass extends SystemClass { - SystemDelegateClass() { - this.hasName("Delegate") - } -} +class SystemDelegateClass extends SystemClass { SystemDelegateClass() { this.hasName("Delegate") } } /** The `System.DivideByZeroException` class. */ class SystemDivideByZeroExceptionClass extends SystemClass { - SystemDivideByZeroExceptionClass() { - this.hasName("DivideByZeroException") - } + SystemDivideByZeroExceptionClass() { this.hasName("DivideByZeroException") } } /** The `System.Enum` class. */ -class SystemEnumClass extends SystemClass { - SystemEnumClass() { - this.hasName("Enum") - } -} +class SystemEnumClass extends SystemClass { SystemEnumClass() { this.hasName("Enum") } } /** The `System.Exception` class. */ class SystemExceptionClass extends SystemClass { - SystemExceptionClass() { - this.hasName("Exception") - } + SystemExceptionClass() { this.hasName("Exception") } } /** The `System.Func` delegate type. */ class SystemFuncDelegateType extends SystemUnboundGenericDelegateType { - SystemFuncDelegateType() { - this.getName().regexpMatch("Func<,*>") - } + SystemFuncDelegateType() { this.getName().regexpMatch("Func<,*>") } /** Gets one of the `Ti` input type parameters. */ TypeParameter getAnInputTypeParameter() { - exists(int i | - i in [0 .. this.getNumberOfTypeParameters() - 2] | + exists(int i | i in [0 .. this.getNumberOfTypeParameters() - 2] | result = this.getTypeParameter(i) ) } @@ -161,236 +112,170 @@ class SystemFuncDelegateType extends SystemUnboundGenericDelegateType { /** The `System.IComparable` interface. */ class SystemIComparableInterface extends SystemInterface { - SystemIComparableInterface() { - this.hasName("IComparable") - } + SystemIComparableInterface() { this.hasName("IComparable") } /** Gets the `CompareTo(object)` method. */ Method getCompareToMethod() { - result.getDeclaringType() = this - and - result.hasName("CompareTo") - and - result.getNumberOfParameters() = 1 - and - result.getParameter(0).getType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("CompareTo") and + result.getNumberOfParameters() = 1 and + result.getParameter(0).getType() instanceof ObjectType and result.getReturnType() instanceof IntType } } /** The `System.IComparable` interface. */ class SystemIComparableTInterface extends SystemUnboundGenericInterface { - SystemIComparableTInterface() { - this.hasName("IComparable<>") - } + SystemIComparableTInterface() { this.hasName("IComparable<>") } /** Gets the `CompareTo(T)` method. */ Method getCompareToMethod() { - result.getDeclaringType() = this - and - result.hasName("CompareTo") - and - result.getNumberOfParameters() = 1 - and - result.getParameter(0).getType() = getTypeParameter(0) - and + result.getDeclaringType() = this and + result.hasName("CompareTo") and + result.getNumberOfParameters() = 1 and + result.getParameter(0).getType() = getTypeParameter(0) and result.getReturnType() instanceof IntType } } /** The `System.IEquatable` interface. */ class SystemIEquatableTInterface extends SystemUnboundGenericInterface { - SystemIEquatableTInterface() { - this.hasName("IEquatable<>") - } + SystemIEquatableTInterface() { this.hasName("IEquatable<>") } /** Gets the `Equals(T)` method. */ Method getEqualsMethod() { - result.getDeclaringType() = this - and - result.hasName("Equals") - and - result.getNumberOfParameters() = 1 - and - result.getParameter(0).getType() = getTypeParameter(0) - and + result.getDeclaringType() = this and + result.hasName("Equals") and + result.getNumberOfParameters() = 1 and + result.getParameter(0).getType() = getTypeParameter(0) and result.getReturnType() instanceof BoolType } } /** The `System.IFormatProvider` interface. */ class SystemIFormatProviderInterface extends SystemInterface { - SystemIFormatProviderInterface() { - this.hasName("IFormatProvider") - } + SystemIFormatProviderInterface() { this.hasName("IFormatProvider") } } /** The `System.Int32` structure. */ class SystemInt32Struct extends IntType { /** Gets the `Parse(string, ...)` method. */ Method getParseMethod() { - result.getDeclaringType() = this - and - result.hasName("Parse") - and - result.getParameter(0).getType() instanceof StringType - and + result.getDeclaringType() = this and + result.hasName("Parse") and + result.getParameter(0).getType() instanceof StringType and result.getReturnType() instanceof IntType } /** Gets the `TryParse(string, ..., out int)` method. */ Method getTryParseMethod() { - result.getDeclaringType() = this - and - result.hasName("TryParse") - and - result.getParameter(0).getType() instanceof StringType - and - result.getParameter(result.getNumberOfParameters() - 1).getType() instanceof IntType - and + result.getDeclaringType() = this and + result.hasName("TryParse") and + result.getParameter(0).getType() instanceof StringType and + result.getParameter(result.getNumberOfParameters() - 1).getType() instanceof IntType and result.getReturnType() instanceof BoolType } } /** The `System.InvalidCastException` class. */ class SystemInvalidCastExceptionClass extends SystemClass { - SystemInvalidCastExceptionClass() { - this.hasName("InvalidCastException") - } + SystemInvalidCastExceptionClass() { this.hasName("InvalidCastException") } } /** The `System.Lazy` class. */ class SystemLazyClass extends SystemUnboundGenericClass { SystemLazyClass() { - this.hasName("Lazy<>") - and + this.hasName("Lazy<>") and this.getNumberOfTypeParameters() = 1 } /** Gets the `Value` property. */ Property getValueProperty() { - result.getDeclaringType() = this - and - result.hasName("Value") - and + result.getDeclaringType() = this and + result.hasName("Value") and result.getType() = getTypeParameter(0) } } /** The `System.NullReferenceException` class. */ class SystemNullReferenceExceptionClass extends SystemClass { - SystemNullReferenceExceptionClass() { - this.hasName("NullReferenceException") - } + SystemNullReferenceExceptionClass() { this.hasName("NullReferenceException") } } /** The `System.Object` class. */ class SystemObjectClass extends SystemClass { - SystemObjectClass() { - this instanceof ObjectType - } + SystemObjectClass() { this instanceof ObjectType } /** Gets the `Equals(object)` method. */ Method getEqualsMethod() { - result.getDeclaringType() = this - and - result.hasName("Equals") - and - result.getNumberOfParameters() = 1 - and - result.getParameter(0).getType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("Equals") and + result.getNumberOfParameters() = 1 and + result.getParameter(0).getType() instanceof ObjectType and result.getReturnType() instanceof BoolType } /** Gets the `Equals(object, object)` method. */ Method getStaticEqualsMethod() { - result.isStatic() - and - result.getDeclaringType() = this - and - result.hasName("Equals") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof ObjectType - and - result.getParameter(1).getType() instanceof ObjectType - and + result.isStatic() and + result.getDeclaringType() = this and + result.hasName("Equals") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof ObjectType and + result.getParameter(1).getType() instanceof ObjectType and result.getReturnType() instanceof BoolType } /** Gets the `ReferenceEquals(object, object)` method. */ Method getReferenceEqualsMethod() { - result.isStatic() - and - result.getDeclaringType() = this - and - result.hasName("ReferenceEquals") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof ObjectType - and - result.getParameter(1).getType() instanceof ObjectType - and + result.isStatic() and + result.getDeclaringType() = this and + result.hasName("ReferenceEquals") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof ObjectType and + result.getParameter(1).getType() instanceof ObjectType and result.getReturnType() instanceof BoolType } /** Gets the `GetHashCode()` method. */ Method getGetHashCodeMethod() { - result.getDeclaringType() = this - and - result.hasName("GetHashCode") - and - result.hasNoParameters() - and + result.getDeclaringType() = this and + result.hasName("GetHashCode") and + result.hasNoParameters() and result.getReturnType() instanceof IntType } /** Gets the `GetType()` method. */ Method getGetTypeMethod() { - result.getDeclaringType() = this - and - result.hasName("GetType") - and - result.hasNoParameters() - and + result.getDeclaringType() = this and + result.hasName("GetType") and + result.hasNoParameters() and result.getReturnType() instanceof SystemTypeClass } /** Gets the `ToString()` method. */ Method getToStringMethod() { - result.getDeclaringType() = this - and - result.hasName("ToString") - and - result.getNumberOfParameters() = 0 - and + result.getDeclaringType() = this and + result.hasName("ToString") and + result.getNumberOfParameters() = 0 and result.getReturnType() instanceof StringType } } /** The `System.OutOfMemoryException` class. */ class SystemOutOfMemoryExceptionClass extends SystemClass { - SystemOutOfMemoryExceptionClass() { - this.hasName("OutOfMemoryException") - } + SystemOutOfMemoryExceptionClass() { this.hasName("OutOfMemoryException") } } /** The `System.OverflowException` class. */ class SystemOverflowExceptionClass extends SystemClass { - SystemOverflowExceptionClass() { - this.hasName("OverflowException") - } + SystemOverflowExceptionClass() { this.hasName("OverflowException") } } /** The `System.Predicate` delegate type. */ class SystemPredicateDelegateType extends SystemUnboundGenericDelegateType { SystemPredicateDelegateType() { - this.hasName("Predicate<>") - and + this.hasName("Predicate<>") and this.getNumberOfTypeParameters() = 1 } } @@ -411,157 +296,113 @@ class SystemStringClass extends StringType { /** Gets the `Replace(string/char, string/char)` method. */ Method getReplaceMethod() { - result.getDeclaringType() = this - and - result.hasName("Replace") - and - result.getNumberOfParameters() = 2 - and + result.getDeclaringType() = this and + result.hasName("Replace") and + result.getNumberOfParameters() = 2 and result.getReturnType() instanceof StringType } /** Gets a `Format(...)` method. */ Method getFormatMethod() { - result.getDeclaringType() = this - and - result.hasName("Format") - and - result.getNumberOfParameters() in [2 .. 5] - and + result.getDeclaringType() = this and + result.hasName("Format") and + result.getNumberOfParameters() in [2 .. 5] and result.getReturnType() instanceof StringType } /** Gets a `Split(...)` method. */ Method getSplitMethod() { - result.getDeclaringType() = this - and - result.hasName("Split") - and - result.getNumberOfParameters() in [1 .. 3] - and + result.getDeclaringType() = this and + result.hasName("Split") and + result.getNumberOfParameters() in [1 .. 3] and result.getReturnType().(ArrayType).getElementType() instanceof StringType } /** Gets a `Substring(...)` method. */ Method getSubstringMethod() { - result.getDeclaringType() = this - and - result.hasName("Substring") - and - result.getNumberOfParameters() in [1 .. 2] - and + result.getDeclaringType() = this and + result.hasName("Substring") and + result.getNumberOfParameters() in [1 .. 2] and result.getReturnType() instanceof StringType } /** Gets a `Concat(...)` method. */ Method getConcatMethod() { - result.getDeclaringType() = this - and - result.hasName("Concat") - and + result.getDeclaringType() = this and + result.hasName("Concat") and result.getReturnType() instanceof StringType } /** Gets the `Copy()` method. */ Method getCopyMethod() { - result.getDeclaringType() = this - and - result.hasName("Copy") - and - result.getNumberOfParameters() = 1 - and - result.getParameter(0).getType() instanceof StringType - and + result.getDeclaringType() = this and + result.hasName("Copy") and + result.getNumberOfParameters() = 1 and + result.getParameter(0).getType() instanceof StringType and result.getReturnType() instanceof StringType } /** Gets a `Join(string, ...)` method. */ Method getJoinMethod() { - result.getDeclaringType() = this - and - result.hasName("Join") - and - result.getNumberOfParameters() > 1 - and - result.getParameter(0).getType() instanceof StringType - and + result.getDeclaringType() = this and + result.hasName("Join") and + result.getNumberOfParameters() > 1 and + result.getParameter(0).getType() instanceof StringType and result.getReturnType() instanceof StringType } /** Gets the `Clone()` method. */ Method getCloneMethod() { - result.getDeclaringType() = this - and - result.hasName("Clone") - and - result.getNumberOfParameters() = 0 - and + result.getDeclaringType() = this and + result.hasName("Clone") and + result.getNumberOfParameters() = 0 and result.getReturnType() instanceof ObjectType } /** Gets the `Insert(int, string)` method. */ Method getInsertMethod() { - result.getDeclaringType() = this - and - result.hasName("Insert") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof IntType - and - result.getParameter(1).getType() instanceof StringType - and + result.getDeclaringType() = this and + result.hasName("Insert") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof IntType and + result.getParameter(1).getType() instanceof StringType and result.getReturnType() instanceof StringType } /** Gets the `Normalize(...)` method. */ Method getNormalizeMethod() { - result.getDeclaringType() = this - and - result.hasName("Normalize") - and - result.getNumberOfParameters() in [0 .. 1] - and + result.getDeclaringType() = this and + result.hasName("Normalize") and + result.getNumberOfParameters() in [0 .. 1] and result.getReturnType() instanceof StringType } /** Gets a `Remove(...)` method. */ Method getRemoveMethod() { - result.getDeclaringType() = this - and - result.hasName("Remove") - and - result.getNumberOfParameters() in [1 .. 2] - and + result.getDeclaringType() = this and + result.hasName("Remove") and + result.getNumberOfParameters() in [1 .. 2] and result.getReturnType() instanceof StringType } /** Gets the `IsNullOrEmpty(string)` method. */ Method getIsNullOrEmptyMethod() { - result.getDeclaringType() = this - and - result.hasName("IsNullOrEmpty") - and - result.isStatic() - and - result.getNumberOfParameters() = 1 - and + result.getDeclaringType() = this and + result.hasName("IsNullOrEmpty") and + result.isStatic() and + result.getNumberOfParameters() = 1 and result.getReturnType() instanceof BoolType } } /** A `ToString()` method. */ class ToStringMethod extends Method { - ToStringMethod() { - this = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() - } + ToStringMethod() { this = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() } } /** The `System.Type` class */ class SystemTypeClass extends SystemClass { - SystemTypeClass() { - this.hasName("Type") - } + SystemTypeClass() { this.hasName("Type") } /** Gets the `FullName` property. */ Property getFullNameProperty() { @@ -572,95 +413,71 @@ class SystemTypeClass extends SystemClass { /** Gets the `InvokeMember(string, ...)` method. */ Method getInvokeMemberMethod() { - result.getDeclaringType() = this - and - result.hasName("InvokeMember") - and - result.getParameter(0).getType() instanceof StringType - and - result.getParameter(3).getType() instanceof ObjectType - and - result.getParameter(4).getType().(ArrayType).getElementType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("InvokeMember") and + result.getParameter(0).getType() instanceof StringType and + result.getParameter(3).getType() instanceof ObjectType and + result.getParameter(4).getType().(ArrayType).getElementType() instanceof ObjectType and result.getReturnType() instanceof ObjectType } /** Gets the `GetMethod(string, ...)` method. */ Method getGetMethodMethod() { - result.getDeclaringType() = this - and - result.hasName("GetMethod") - and - result.getParameter(0).getType() instanceof StringType - and + result.getDeclaringType() = this and + result.hasName("GetMethod") and + result.getParameter(0).getType() instanceof StringType and result.getReturnType() instanceof SystemReflectionMethodInfoClass } } /** The `System.Uri` class. */ class SystemUriClass extends SystemClass { - SystemUriClass() { - this.hasName("Uri") - } + SystemUriClass() { this.hasName("Uri") } /** Gets the `PathAndQuery` property. */ Property getPathAndQueryProperty() { - result.getDeclaringType() = this - and - result.hasName("PathAndQuery") - and + result.getDeclaringType() = this and + result.hasName("PathAndQuery") and result.getType() instanceof StringType } /** Gets the `Query` property. */ Property getQueryProperty() { - result.getDeclaringType() = this - and - result.hasName("Query") - and + result.getDeclaringType() = this and + result.hasName("Query") and result.getType() instanceof StringType } /** Gets the `OriginalString` property. */ Property getOriginalStringProperty() { - result.getDeclaringType() = this - and - result.hasName("OriginalString") - and + result.getDeclaringType() = this and + result.hasName("OriginalString") and result.getType() instanceof StringType } } /** The `System.ValueType` class. */ class SystemValueTypeClass extends SystemClass { - SystemValueTypeClass() { - this.hasName("ValueType") - } + SystemValueTypeClass() { this.hasName("ValueType") } } /** The `System.IntPtr` type. */ class SystemIntPtrType extends ValueType { SystemIntPtrType() { - this = any(SystemNamespace n).getATypeDeclaration() - and + this = any(SystemNamespace n).getATypeDeclaration() and this.hasName("IntPtr") } } /** The `System.IDisposable` interface. */ class SystemIDisposableInterface extends SystemInterface { - SystemIDisposableInterface() { - this.hasName("IDisposable") - } + SystemIDisposableInterface() { this.hasName("IDisposable") } /** Gets the `Dispose()` method. */ Method getDisposeMethod() { - result.getDeclaringType() = this - and - result.hasName("Dispose") - and - result.getNumberOfParameters() = 0 - and + result.getDeclaringType() = this and + result.hasName("Dispose") and + result.getNumberOfParameters() = 0 and result.getReturnType() instanceof VoidType } } @@ -668,8 +485,7 @@ class SystemIDisposableInterface extends SystemInterface { /** A method that overrides `int object.GetHashCode()`. */ class GetHashCodeMethod extends Method { GetHashCodeMethod() { - exists(Method m | - m = any(SystemObjectClass c).getGetHashCodeMethod() | + exists(Method m | m = any(SystemObjectClass c).getGetHashCodeMethod() | this = m.getAnOverrider*() ) } @@ -678,10 +494,7 @@ class GetHashCodeMethod extends Method { /** A method that overrides `bool object.Equals(object)`. */ class EqualsMethod extends Method { EqualsMethod() { - exists(Method m | - m = any(SystemObjectClass c).getEqualsMethod() | - this = m.getAnOverrider*() - ) + exists(Method m | m = any(SystemObjectClass c).getEqualsMethod() | this = m.getAnOverrider*()) } } @@ -690,7 +503,8 @@ class IEquatableEqualsMethod extends Method { IEquatableEqualsMethod() { exists(Method m | m = any(SystemIEquatableTInterface i).getAConstructedGeneric().getAMethod() and - m.getSourceDeclaration() = any(SystemIEquatableTInterface i).getEqualsMethod() | + m.getSourceDeclaration() = any(SystemIEquatableTInterface i).getEqualsMethod() + | this = m or getAnUltimateImplementee() = m ) } @@ -703,9 +517,7 @@ class IEquatableEqualsMethod extends Method { * or an implementation of `IEquatable.Equals(T)` which is called * from the `object.Equals(object)` method inherited by `t`. */ -predicate implementsEquals(ValueOrRefType t) { - getInvokedEqualsMethod(t).getDeclaringType() = t -} +predicate implementsEquals(ValueOrRefType t) { getInvokedEqualsMethod(t).getDeclaringType() = t } /** * Gets the equals method that will be invoked on a value `x` @@ -725,9 +537,7 @@ Method getInvokedEqualsMethod(ValueOrRefType t) { ) } -private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t) { - t.hasMethod(result) -} +private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t) { t.hasMethod(result) } /** * Equals method `eq` is inherited by `t`, `t` overrides `IEquatable.Equals(T)` @@ -754,7 +564,8 @@ private IEquatableEqualsMethod getInvokedIEquatableEqualsMethod(ValueOrRefType t eq = getInheritedEqualsMethod(t.getBaseClass()) and exists(IEquatableEqualsMethod ieem | result = ieem.getAnOverrider*() and - eq.getDeclaringType() = ieem.getDeclaringType() | + eq.getDeclaringType() = ieem.getDeclaringType() + | not ieem.fromSource() or callsEqualsMethod(eq, ieem) @@ -772,8 +583,7 @@ private predicate callsEqualsMethod(EqualsMethod eq, IEquatableEqualsMethod ieem /** A method that implements `void IDisposable.Dispose()`. */ class DisposeMethod extends Method { DisposeMethod() { - exists(Method m | - m = any(SystemIDisposableInterface i).getDisposeMethod() | + exists(Method m | m = any(SystemIDisposableInterface i).getDisposeMethod() | this = m or this.getAnUltimateImplementee() = m ) } @@ -796,9 +606,7 @@ library class DisposeBoolMethod extends Method { * or an implementation of a method `Dispose(bool)` which is called * from the `IDisposable.Dispose()` method inherited by `t`. */ -predicate implementsDispose(ValueOrRefType t) { - getInvokedDisposeMethod(t).getDeclaringType() = t -} +predicate implementsDispose(ValueOrRefType t) { getInvokedDisposeMethod(t).getDeclaringType() = t } /** * Gets the dispose method that will be invoked on a value `x` @@ -818,9 +626,7 @@ Method getInvokedDisposeMethod(ValueOrRefType t) { ) } -private DisposeMethod getInheritedDisposeMethod(ValueOrRefType t) { - t.hasMethod(result) -} +private DisposeMethod getInheritedDisposeMethod(ValueOrRefType t) { t.hasMethod(result) } /** * Dispose method `disp` is inherited by `t`, `t` overrides a `void Dispose(bool)` @@ -847,7 +653,8 @@ private DisposeBoolMethod getInvokedDiposeBoolMethod(ValueOrRefType t, DisposeMe disp = getInheritedDisposeMethod(t.getBaseClass()) and exists(DisposeBoolMethod dbm | result = dbm.getAnOverrider*() and - disp.getDeclaringType() = dbm.getDeclaringType() | + disp.getDeclaringType() = dbm.getDeclaringType() + | not disp.fromSource() or exists(MethodCall callToDerivedDispose | @@ -859,21 +666,13 @@ private DisposeBoolMethod getInvokedDiposeBoolMethod(ValueOrRefType t, DisposeMe /** A struct in the `System` namespace. */ class SystemStruct extends Struct { - SystemStruct() { - this.getNamespace() instanceof SystemNamespace - } + SystemStruct() { this.getNamespace() instanceof SystemNamespace } } /** `System.Guid` struct. */ -class SystemGuid extends SystemStruct { - SystemGuid() { - this.hasName("Guid") - } -} +class SystemGuid extends SystemStruct { SystemGuid() { this.hasName("Guid") } } /** The `System.NotImplementedException` class. */ class SystemNotImplementedExceptionClass extends SystemClass { - SystemNotImplementedExceptionClass() { - this.hasName("NotImplementedException") - } + SystemNotImplementedExceptionClass() { this.hasName("NotImplementedException") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/WCF.qll b/csharp/ql/src/semmle/code/csharp/frameworks/WCF.qll index 75c539078bf..a9505388a92 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/WCF.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/WCF.qll @@ -1,4 +1,5 @@ /** Provides definitions related to Windows Communication Foundation (WCF). */ + import csharp /** A `ServiceContract` attribute. */ @@ -31,9 +32,7 @@ class DataMemberAttribute extends Attribute { /** A data contract class. */ class DataContractClass extends Class { - DataContractClass() { - this.getAnAttribute() instanceof DataContractAttribute - } + DataContractClass() { this.getAnAttribute() instanceof DataContractAttribute } /** A data member of the data contract. */ Declaration getADataMember() { diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Owin.qll b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Owin.qll index 2a54980bc7f..fad261dec93 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Owin.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/microsoft/Owin.qll @@ -3,6 +3,7 @@ * * OWIN defines a standard interface between .NET web servers and web applications. */ + import csharp import semmle.code.csharp.frameworks.Microsoft diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/CodeDom.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/CodeDom.qll index b5e29ee9db1..400e9954866 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/CodeDom.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/CodeDom.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.CodeDom`. */ + import csharp private import semmle.code.csharp.frameworks.System diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Collections.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Collections.qll index 2fa9822ced3..e932740cc02 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Collections.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Collections.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Collections`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,59 +13,42 @@ class SystemCollectionsNamespace extends Namespace { /** An interface in the `System.Collections` namespace. */ class SystemCollectionsInterface extends Interface { - SystemCollectionsInterface() { - this.getNamespace() instanceof SystemCollectionsNamespace - } + SystemCollectionsInterface() { this.getNamespace() instanceof SystemCollectionsNamespace } } /** The `System.Collections.IComparer` interface. */ class SystemCollectionsIComparerInterface extends SystemCollectionsInterface { - SystemCollectionsIComparerInterface() { - this.hasName("IComparer") - } + SystemCollectionsIComparerInterface() { this.hasName("IComparer") } /** Gets the `Compare(object, object)` method. */ Method getCompareMethod() { - result.getDeclaringType() = this - and - result.hasName("Compare") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof ObjectType - and - result.getParameter(1).getType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("Compare") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof ObjectType and + result.getParameter(1).getType() instanceof ObjectType and result.getReturnType() instanceof IntType } } /** The `System.Collections.IEnumerable` interface. */ class SystemCollectionsIEnumerableInterface extends SystemCollectionsInterface { - SystemCollectionsIEnumerableInterface() { - this.hasName("IEnumerable") - } + SystemCollectionsIEnumerableInterface() { this.hasName("IEnumerable") } } /** The `System.Collections.IEnumerator` interface. */ class SystemCollectionsIEnumeratorInterface extends SystemCollectionsInterface { - SystemCollectionsIEnumeratorInterface() { - this.hasName("IEnumerator") - } + SystemCollectionsIEnumeratorInterface() { this.hasName("IEnumerator") } /** Gets the `Current` property. */ Property getCurrentProperty() { - result.getDeclaringType() = this - and - result.hasName("Current") - and + result.getDeclaringType() = this and + result.hasName("Current") and result.getType() instanceof ObjectType } } /** The `System.Collections.ICollection` interface. */ class SystemCollectionsICollectionInterface extends SystemCollectionsInterface { - SystemCollectionsICollectionInterface() { - this.hasName("ICollection") - } + SystemCollectionsICollectionInterface() { this.hasName("ICollection") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Data.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Data.qll index 09f54916024..f0e9fe29e96 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Data.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Data.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Data`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,47 +13,33 @@ class SystemDataNamespace extends Namespace { /** An interface in the `System.Data` namespace. */ class SystemDataInterface extends Interface { - SystemDataInterface() { - this.getNamespace() instanceof SystemDataNamespace - } + SystemDataInterface() { this.getNamespace() instanceof SystemDataNamespace } } /** The `System.Data.IDbCommand` interface. */ class SystemDataIDbCommandInterface extends SystemDataInterface { - SystemDataIDbCommandInterface() { - this.hasName("IDbCommand") - } + SystemDataIDbCommandInterface() { this.hasName("IDbCommand") } /** Gets the `CommandText` property. */ Property getCommandTextProperty() { - result.getDeclaringType() = this - and - result.hasName("CommandText") - and + result.getDeclaringType() = this and + result.hasName("CommandText") and result.getType() instanceof StringType } } /** The `System.Data.IDbConnection` interface. */ class SystemDataIDbConnectionInterface extends SystemDataInterface { - SystemDataIDbConnectionInterface() { - this.hasName("IDbConnection") - } + SystemDataIDbConnectionInterface() { this.hasName("IDbConnection") } /** Gets the `ConnectionString` property. */ - Property getAConnectionStringProperty() { - result = this.getProperty("ConnectionString") - } + Property getAConnectionStringProperty() { result = this.getProperty("ConnectionString") } } /** A class that implements `System.Data.IDbConnection`. */ class SystemDataConnectionClass extends Class { - SystemDataConnectionClass() { - this.getABaseType+() instanceof SystemDataIDbConnectionInterface - } + SystemDataConnectionClass() { this.getABaseType+() instanceof SystemDataIDbConnectionInterface } /** Gets the `ConnectionString` property. */ - Property getConnectionStringProperty() { - result = this.getProperty("ConnectionString") - } + Property getConnectionStringProperty() { result = this.getProperty("ConnectionString") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Diagnostics.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Diagnostics.qll index 48119f599d8..3adb9776dba 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Diagnostics.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Diagnostics.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Diagnostics`. */ + import semmle.code.csharp.Type private import semmle.code.csharp.frameworks.System @@ -12,9 +13,7 @@ class SystemDiagnosticsNamespace extends Namespace { /** A class in the `System.Diagnostics` namespace. */ class SystemDiagnosticsClass extends Class { - SystemDiagnosticsClass() { - this.getNamespace() instanceof SystemDiagnosticsNamespace - } + SystemDiagnosticsClass() { this.getNamespace() instanceof SystemDiagnosticsNamespace } } /** The `System.Diagnostics.Debug` class. */ @@ -26,21 +25,16 @@ class SystemDiagnosticsDebugClass extends SystemDiagnosticsClass { /** Gets and `Assert(bool, ...)` method. */ Method getAssertMethod() { - result.getDeclaringType() = this - and - result.hasName("Assert") - and - result.getParameter(0).getType() instanceof BoolType - and + result.getDeclaringType() = this and + result.hasName("Assert") and + result.getParameter(0).getType() instanceof BoolType and result.getReturnType() instanceof VoidType } } /** The `System.Diagnostics.ProcessStartInfo` class. */ class SystemDiagnosticsProcessStartInfoClass extends SystemDiagnosticsClass { - SystemDiagnosticsProcessStartInfoClass() { - this.hasName("ProcessStartInfo") - } + SystemDiagnosticsProcessStartInfoClass() { this.hasName("ProcessStartInfo") } /** Gets the `Arguments` property. */ Property getArgumentsProperty() { result = this.getProperty("Arguments") } @@ -54,9 +48,7 @@ class SystemDiagnosticsProcessStartInfoClass extends SystemDiagnosticsClass { /** The `System.Diagnostics.Process` class. */ class SystemDiagnosticsProcessClass extends SystemDiagnosticsClass { - SystemDiagnosticsProcessClass() { - this.hasName("Process") - } + SystemDiagnosticsProcessClass() { this.hasName("Process") } /** Get a `Start( ...)` method. */ Method getAStartMethod() { diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/DirectoryServices.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/DirectoryServices.qll index 660415e52cd..327eaee35a9 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/DirectoryServices.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/DirectoryServices.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.DirectoryServices`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,21 +13,15 @@ class SystemDirectoryServicesNamespace extends Namespace { /** A class in the `System.DirectoryServices` namespace. */ class SystemDirectoryServicesClass extends Class { - SystemDirectoryServicesClass() { - this.getNamespace() instanceof SystemDirectoryServicesNamespace - } + SystemDirectoryServicesClass() { this.getNamespace() instanceof SystemDirectoryServicesNamespace } } /** The `System.DirectoryServices.DirectorySearcher` class. */ class SystemDirectoryServicesDirectorySearcherClass extends SystemDirectoryServicesClass { - SystemDirectoryServicesDirectorySearcherClass() { - this.hasName("DirectorySearcher") - } + SystemDirectoryServicesDirectorySearcherClass() { this.hasName("DirectorySearcher") } } /** The `System.DirectoryServices.DirectoryEntry` class. */ class SystemDirectoryServicesDirectoryEntryClass extends SystemDirectoryServicesClass { - SystemDirectoryServicesDirectoryEntryClass() { - this.hasName("DirectoryEntry") - } + SystemDirectoryServicesDirectoryEntryClass() { this.hasName("DirectoryEntry") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/IO.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/IO.qll index f645df32b2c..79867f8432b 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/IO.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/IO.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.IO`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,58 +13,38 @@ class SystemIONamespace extends Namespace { /** A class in the `System.IO` namespace. */ class SystemIOClass extends Class { - SystemIOClass() { - this.getNamespace() instanceof SystemIONamespace - } + SystemIOClass() { this.getNamespace() instanceof SystemIONamespace } } /** The `System.IO.Directory` class. */ class SystemIODirectoryClass extends SystemIOClass { - SystemIODirectoryClass() { - this.hasName("Directory") - } + SystemIODirectoryClass() { this.hasName("Directory") } } /** The `System.IO.File` class. */ -class SystemIOFileClass extends SystemIOClass { - SystemIOFileClass() { - this.hasName("File") - } -} +class SystemIOFileClass extends SystemIOClass { SystemIOFileClass() { this.hasName("File") } } /** The `System.IO.FileStream` class. */ class SystemIOFileStreamClass extends SystemIOClass { - SystemIOFileStreamClass() { - this.hasName("FileStream") - } + SystemIOFileStreamClass() { this.hasName("FileStream") } } /** The `System.IO.StreamWriter` class. */ class SystemIOStreamWriterClass extends SystemIOClass { - SystemIOStreamWriterClass() { - this.hasName("StreamWriter") - } + SystemIOStreamWriterClass() { this.hasName("StreamWriter") } } /** The `System.IO.Path` class. */ -class SystemIOPathClass extends SystemIOClass { - SystemIOPathClass() { - this.hasName("Path") - } -} +class SystemIOPathClass extends SystemIOClass { SystemIOPathClass() { this.hasName("Path") } } /** The `System.IO.StringReader` class. */ class SystemIOStringReaderClass extends SystemIOClass { - SystemIOStringReaderClass() { - this.hasName("StringReader") - } + SystemIOStringReaderClass() { this.hasName("StringReader") } } /** The `System.IO.Stream` class. */ class SystemIOStreamClass extends SystemIOClass { - SystemIOStreamClass() { - this.hasName("Stream") - } + SystemIOStreamClass() { this.hasName("Stream") } /** Gets a method that performs a read. */ Method getAReadMethod() { @@ -79,38 +60,27 @@ class SystemIOStreamClass extends SystemIOClass { /** Gets the `Read(byte[], int, int)` method. */ Method getReadMethod() { - result.getDeclaringType() = this - and - result.hasName("Read") - and - result.getNumberOfParameters() = 3 - and - result.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType - and - result.getParameter(1).getType() instanceof IntType - and - result.getParameter(2).getType() instanceof IntType - and + result.getDeclaringType() = this and + result.hasName("Read") and + result.getNumberOfParameters() = 3 and + result.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and + result.getParameter(1).getType() instanceof IntType and + result.getParameter(2).getType() instanceof IntType and result.getReturnType() instanceof IntType } /** Gets the `ReadByte()` method. */ Method getReadByteMethod() { - result.getDeclaringType() = this - and - result.hasName("ReadByte") - and - result.getNumberOfParameters() = 0 - and + result.getDeclaringType() = this and + result.hasName("ReadByte") and + result.getNumberOfParameters() = 0 and result.getReturnType() instanceof IntType } } /** The `System.IO.MemoryStream` class. */ class SystemIOMemoryStreamClass extends SystemIOClass { - SystemIOMemoryStreamClass() { - this.hasName("MemoryStream") - } + SystemIOMemoryStreamClass() { this.hasName("MemoryStream") } /** Gets the `ToArray` Method. */ Method getToArrayMethod() { diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Linq.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Linq.qll index dfdf121d23e..1bdac1658d9 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Linq.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Linq.qll @@ -1,11 +1,11 @@ /** * Provides classes related to the namespace `System.Linq`. */ + private import csharp as csharp private import semmle.code.csharp.frameworks.System as System module SystemLinq { - /** The `System.Linq` namespace. */ class Namespace extends csharp::Namespace { Namespace() { @@ -15,9 +15,5 @@ module SystemLinq { } /** A class in the `System.Linq` namespace. */ - class Class extends csharp::Class { - Class() { - this.getNamespace() instanceof Namespace - } - } + class Class extends csharp::Class { Class() { this.getNamespace() instanceof Namespace } } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Net.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Net.qll index 40fab84c545..7c0aee741db 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Net.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Net.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Net`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,85 +13,56 @@ class SystemNetNamespace extends Namespace { /** A class in the `System.Net` namespace. */ class SystemNetClass extends Class { - SystemNetClass() { - this.getNamespace() instanceof SystemNetNamespace - } + SystemNetClass() { this.getNamespace() instanceof SystemNetNamespace } } /** The `System.Net.WebUtility` class. */ class SystemNetWebUtility extends SystemNetClass { - SystemNetWebUtility() { - this.hasName("WebUtility") - } + SystemNetWebUtility() { this.hasName("WebUtility") } /** Gets an `HtmlEncode` method. */ - Method getAnHtmlEncodeMethod() { - result = this.getAMethod("HtmlEncode") - } + Method getAnHtmlEncodeMethod() { result = this.getAMethod("HtmlEncode") } /** Gets an `UrlEncode` method. */ - Method getAnUrlEncodeMethod() { - result = this.getAMethod("UrlEncode") - } + Method getAnUrlEncodeMethod() { result = this.getAMethod("UrlEncode") } } /** The `System.Net.HttpListenerResponse` class. */ class SystemNetHttpListenerResponseClass extends SystemNetClass { - SystemNetHttpListenerResponseClass() { - this.hasName("HttpListenerResponse") - } + SystemNetHttpListenerResponseClass() { this.hasName("HttpListenerResponse") } /** Gets the `OutputStream` Property. */ - Property getOutputStreamProperty() { - result = this.getProperty("OutputStream") - } + Property getOutputStreamProperty() { result = this.getProperty("OutputStream") } } - /** The `System.Net.HttpListenerResponse` class. */ class SystemNetHttpListenerRequestClass extends SystemNetClass { - SystemNetHttpListenerRequestClass() { - this.hasName("HttpListenerRequest") - } + SystemNetHttpListenerRequestClass() { this.hasName("HttpListenerRequest") } } /** The `System.Net.Dns` class. */ class SystemNetDnsClass extends SystemNetClass { - SystemNetDnsClass() { - this.hasName("Dns") - } + SystemNetDnsClass() { this.hasName("Dns") } /** Gets the `GetHostByAddress` method. */ - Method getGetHostByAddressMethod() { - result = this.getAMethod("GetHostByAddress") - } + Method getGetHostByAddressMethod() { result = this.getAMethod("GetHostByAddress") } } /** The `System.Net.IPHostEntry` class. */ class SystemNetIPHostEntryClass extends SystemNetClass { - SystemNetIPHostEntryClass() { - this.hasName("IPHostEntry") - } + SystemNetIPHostEntryClass() { this.hasName("IPHostEntry") } /** Gets the `HostName` property. */ - Property getHostNameProperty() { - result = this.getProperty("HostName") - } + Property getHostNameProperty() { result = this.getProperty("HostName") } /** Gets the `Aliases` property. */ - Property getAliasesProperty() { - result = this.getProperty("Aliases") - } + Property getAliasesProperty() { result = this.getProperty("Aliases") } } /** The `System.Net.Cookie` class. */ class SystemNetCookieClass extends SystemNetClass { - SystemNetCookieClass() { - this.hasName("Cookie") - } + SystemNetCookieClass() { this.hasName("Cookie") } /** Gets the `Value` property. */ - Property getValueProperty() { - result = this.getProperty("Value") - } + Property getValueProperty() { result = this.getProperty("Value") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Reflection.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Reflection.qll index a4e5bfaf5a6..8779b21dd27 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Reflection.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Reflection.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Reflection`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,51 +13,35 @@ class SystemReflectionNamespace extends Namespace { /** A class in the `System.Reflection` namespace. */ class SystemReflectionClass extends Class { - SystemReflectionClass() { - this.getNamespace() instanceof SystemReflectionNamespace - } + SystemReflectionClass() { this.getNamespace() instanceof SystemReflectionNamespace } } /** The `System.Reflection.MethodBase` class. */ class SystemReflectionMethodBaseClass extends SystemReflectionClass { - SystemReflectionMethodBaseClass() { - this.hasName("MethodBase") - } + SystemReflectionMethodBaseClass() { this.hasName("MethodBase") } /** Gets the `Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)` method. */ Method getInvokeMethod1() { - result.getDeclaringType() = this - and - result.hasName("Invoke") - and - result.getNumberOfParameters() = 5 - and - result.getParameter(0).getType() instanceof ObjectType - and - result.getParameter(3).getType().(ArrayType).getElementType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("Invoke") and + result.getNumberOfParameters() = 5 and + result.getParameter(0).getType() instanceof ObjectType and + result.getParameter(3).getType().(ArrayType).getElementType() instanceof ObjectType and result.getReturnType() instanceof ObjectType } /** Gets the `Invoke(Object, Object[])` method. */ Method getInvokeMethod2() { - result.getDeclaringType() = this - and - result.hasName("Invoke") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof ObjectType - and - result.getParameter(1).getType().(ArrayType).getElementType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("Invoke") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof ObjectType and + result.getParameter(1).getType().(ArrayType).getElementType() instanceof ObjectType and result.getReturnType() instanceof ObjectType } } /** The `System.Reflection.MethodInfo` class. */ class SystemReflectionMethodInfoClass extends SystemReflectionClass { - SystemReflectionMethodInfoClass() { - this.hasName("MethodInfo") - } + SystemReflectionMethodInfoClass() { this.hasName("MethodInfo") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Runtime.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Runtime.qll index 8c03fc49420..467f3234114 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Runtime.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Runtime.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Runtime`. */ + import csharp private import semmle.code.csharp.frameworks.System diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Security.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Security.qll index 1f18016ead4..02325e19383 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Security.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Security.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Security`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,7 +13,5 @@ class SystemSecurityNamespace extends Namespace { /** A class in the `System.Security` namespace. */ class SystemSecurityClass extends Class { - SystemSecurityClass() { - this.getNamespace() instanceof SystemSecurityNamespace - } + SystemSecurityClass() { this.getNamespace() instanceof SystemSecurityNamespace } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Text.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Text.qll index 4b50128cf1d..67c171976cd 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Text.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Text.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Text`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,41 +13,27 @@ class SystemTextNamespace extends Namespace { /** A class in the `System.Text` namespace. */ class SystemTextClass extends Class { - SystemTextClass() { - this.getNamespace() instanceof SystemTextNamespace - } + SystemTextClass() { this.getNamespace() instanceof SystemTextNamespace } } /** The `System.Text.StringBuilder` class. */ class SystemTextStringBuilderClass extends SystemTextClass { - SystemTextStringBuilderClass() { - this.hasName("StringBuilder") - } + SystemTextStringBuilderClass() { this.hasName("StringBuilder") } /** Gets the `AppendFormat` method. */ - Method getAppendFormatMethod() { - result = this.getAMethod("AppendFormat") - } + Method getAppendFormatMethod() { result = this.getAMethod("AppendFormat") } } /** The `System.Text.Encoding` class. */ class SystemTextEncodingClass extends SystemTextClass { - SystemTextEncodingClass() { - this.hasName("Encoding") - } + SystemTextEncodingClass() { this.hasName("Encoding") } /** Gets the `GetBytes` method. */ - Method getGetBytesMethod() { - result = this.getAMethod("GetBytes") - } + Method getGetBytesMethod() { result = this.getAMethod("GetBytes") } /** Gets the `GetString` method. */ - Method getGetStringMethod() { - result = this.getAMethod("GetString") - } + Method getGetStringMethod() { result = this.getAMethod("GetString") } /** Gets the `GetChars` method. */ - Method getGetCharsMethod() { - result = this.getAMethod("GetChars") - } + Method getGetCharsMethod() { result = this.getAMethod("GetChars") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Threading.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Threading.qll index 3c147882d19..92d43a13636 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Threading.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Threading.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Threading`. */ + import csharp private import semmle.code.csharp.frameworks.System diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Web.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Web.qll index a46926c8342..8552c028c89 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Web.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Web.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Web`. */ + import csharp private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.frameworks.system.collections.Specialized @@ -13,113 +14,83 @@ class SystemWebNamespace extends Namespace { /** A class in the `System.Web` namespace. */ class SystemWebClass extends Class { - SystemWebClass() { - this.getNamespace() instanceof SystemWebNamespace - } + SystemWebClass() { this.getNamespace() instanceof SystemWebNamespace } } /** An interface in the `System.Web` namespace. */ class SystemWebInterface extends Interface { - SystemWebInterface() { - this.getNamespace() instanceof SystemWebNamespace - } + SystemWebInterface() { this.getNamespace() instanceof SystemWebNamespace } } /** The `System.Web.HttpRequest` class. */ class SystemWebHttpRequestClass extends SystemWebClass { - SystemWebHttpRequestClass() { - this.hasName("HttpRequest") - } + SystemWebHttpRequestClass() { this.hasName("HttpRequest") } /** Gets the `NameValueCollection QueryString` property. */ IndexerProperty getQueryStringProperty() { - result.getDeclaringType() = this - and - result.hasName("QueryString") - and + result.getDeclaringType() = this and + result.hasName("QueryString") and result.getType() instanceof SystemCollectionsSpecializedNameValueCollectionClass } /** Gets the `NameValueCollection Headers` property. */ IndexerProperty getHeadersProperty() { - result.getDeclaringType() = this - and - result.hasName("Headers") - and + result.getDeclaringType() = this and + result.hasName("Headers") and result.getType() instanceof SystemCollectionsSpecializedNameValueCollectionClass } /** Gets the `string RawUrl` property. */ Property getRawUrlProperty() { - result.getDeclaringType() = this - and - result.hasName("RawUrl") - and + result.getDeclaringType() = this and + result.hasName("RawUrl") and result.getType() instanceof StringType } /** Gets the `UnvalidatedRequestValues Unvalidated` property. */ Property getUnvalidatedProperty() { - result.getDeclaringType() = this - and - result.hasName("Unvalidated") - and + result.getDeclaringType() = this and + result.hasName("Unvalidated") and result.getType() instanceof SystemWebUnvalidatedRequestValues } /** Gets the `Uri Url` property. */ Property getUrlProperty() { - result.getDeclaringType() = this - and - result.hasName("Url") - and + result.getDeclaringType() = this and + result.hasName("Url") and result.getType() instanceof SystemUriClass } } /** The `System.Web.UnvalidatedRequestValues` class. */ class SystemWebUnvalidatedRequestValues extends SystemWebClass { - SystemWebUnvalidatedRequestValues() { - this.hasName("UnvalidatedRequestValues") - } + SystemWebUnvalidatedRequestValues() { this.hasName("UnvalidatedRequestValues") } } /** The `System.Web.UnvalidatedRequestValuesBase` class. */ class SystemWebUnvalidatedRequestValuesBase extends SystemWebClass { - SystemWebUnvalidatedRequestValuesBase() { - this.hasName("UnvalidatedRequestValuesBase") - } + SystemWebUnvalidatedRequestValuesBase() { this.hasName("UnvalidatedRequestValuesBase") } } /** The `System.Web.HttpRequestMessage` class. */ class SystemWebHttpRequestMessageClass extends SystemWebClass { - SystemWebHttpRequestMessageClass() { - this.hasName("HttpRequestMessage") - } + SystemWebHttpRequestMessageClass() { this.hasName("HttpRequestMessage") } } /** The `System.Web.HttpRequestBase` class. */ class SystemWebHttpRequestBaseClass extends SystemWebClass { - SystemWebHttpRequestBaseClass() { - this.hasName("HttpRequestBase") - } + SystemWebHttpRequestBaseClass() { this.hasName("HttpRequestBase") } } /** The `System.Web.HttpResponse` class. */ class SystemWebHttpResponseClass extends SystemWebClass { - SystemWebHttpResponseClass() { - this.hasName("HttpResponse") - } + SystemWebHttpResponseClass() { this.hasName("HttpResponse") } /** Gets the `AddHeader` method. */ - Method getAddHeaderMethod() { - result = this.getAMethod("AddHeader") - } + Method getAddHeaderMethod() { result = this.getAMethod("AddHeader") } /** Gets the `AppendHeader` method. */ - Method getAppendHeaderMethod() { - result = this.getAMethod("AppendHeader") - } + Method getAppendHeaderMethod() { result = this.getAMethod("AppendHeader") } /** Gets a `Write` method. */ Method getAWriteMethod() { @@ -154,9 +125,7 @@ class SystemWebHttpResponseClass extends SystemWebClass { /** The `System.Web.HttpResponseBase` class. */ class SystemWebHttpResponseBaseClass extends SystemWebClass { - SystemWebHttpResponseBaseClass() { - this.hasName("HttpResponseBase") - } + SystemWebHttpResponseBaseClass() { this.hasName("HttpResponseBase") } /** Gets a `Write` method. */ Method getAWriteMethod() { @@ -185,102 +154,66 @@ class SystemWebHttpResponseBaseClass extends SystemWebClass { /** A subtype of `System.Web.HttpApplication. */ class WebApplication extends Class { - WebApplication() { - this.getABaseType*().(SystemWebClass).hasName("HttpApplication") - } + WebApplication() { this.getABaseType*().(SystemWebClass).hasName("HttpApplication") } /** Gets the `Application_Start` Method. */ - Method getApplication_StartMethod() { - result = this.getAMethod("Application_Start") - } + Method getApplication_StartMethod() { result = this.getAMethod("Application_Start") } } /** The `System.Web.HttpServerUtility` class. */ class SystemWebHttpServerUtility extends SystemWebClass { - SystemWebHttpServerUtility() { - this.hasName("HttpServerUtility") - } + SystemWebHttpServerUtility() { this.hasName("HttpServerUtility") } /** Gets an `HtmlEncode` method. */ - Method getAnHtmlEncodeMethod() { - result = this.getAMethod("HtmlEncode") - } + Method getAnHtmlEncodeMethod() { result = this.getAMethod("HtmlEncode") } /** Gets the `Transfer` method. */ - Method getTransferMethod() { - result = this.getAMethod("Transfer") - } + Method getTransferMethod() { result = this.getAMethod("Transfer") } /** Gets an `UrlEncode` method. */ - Method getAnUrlEncodeMethod() { - result = this.getAMethod("UrlEncode") - } + Method getAnUrlEncodeMethod() { result = this.getAMethod("UrlEncode") } } /** The `System.Web.HttpUtility` class. */ class SystemWebHttpUtility extends SystemWebClass { - SystemWebHttpUtility() { - this.hasName("HttpUtility") - } + SystemWebHttpUtility() { this.hasName("HttpUtility") } /** Gets an `HtmlAttributeEncode` method. */ - Method getAnHtmlAttributeEncodeMethod() { - result = this.getAMethod("HtmlAttributeEncode") - } + Method getAnHtmlAttributeEncodeMethod() { result = this.getAMethod("HtmlAttributeEncode") } /** Gets an `HtmlEncode` method. */ - Method getAnHtmlEncodeMethod() { - result = this.getAMethod("HtmlEncode") - } + Method getAnHtmlEncodeMethod() { result = this.getAMethod("HtmlEncode") } /** Gets a `JavaScriptStringEncode` method. */ - Method getAJavaScriptStringEncodeMethod() { - result = this.getAMethod("JavaScriptStringEncode") - } + Method getAJavaScriptStringEncodeMethod() { result = this.getAMethod("JavaScriptStringEncode") } /** Gets an `UrlEncode` method. */ - Method getAnUrlEncodeMethod() { - result = this.getAMethod("UrlEncode") - } + Method getAnUrlEncodeMethod() { result = this.getAMethod("UrlEncode") } } /** The `System.Web.HttpCookie` class. */ class SystemWebHttpCookie extends SystemWebClass { - SystemWebHttpCookie() { - this.hasName("HttpCookie") - } + SystemWebHttpCookie() { this.hasName("HttpCookie") } /** Gets the `Value` property. */ - Property getValueProperty() { - result = this.getProperty("Value") - } + Property getValueProperty() { result = this.getProperty("Value") } /** Gets the `Values` property. */ - IndexerProperty getValuesProperty() { - result = this.getProperty("Values") - } + IndexerProperty getValuesProperty() { result = this.getProperty("Values") } /** Gets the `Secure` property. */ - Property getSecureProperty() { - result = this.getProperty("Secure") - } + Property getSecureProperty() { result = this.getProperty("Secure") } } /** The `System.Web.IHtmlString` class. */ class SystemWebIHtmlString extends SystemWebInterface { - SystemWebIHtmlString() { - this.hasName("IHtmlString") - } + SystemWebIHtmlString() { this.hasName("IHtmlString") } /** Gets the `ToHtmlString` Method. */ - Method getToHtmlStringMethod() { - result = this.getAMethod("ToHtmlString") - } + Method getToHtmlStringMethod() { result = this.getAMethod("ToHtmlString") } } /** The `System.Web.HtmlString` class. */ class SystemWebHtmlString extends SystemWebClass { - SystemWebHtmlString() { - this.hasName("HtmlString") - } + SystemWebHtmlString() { this.hasName("HtmlString") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Windows.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Windows.qll index f30c8433a12..7d4aaa3075e 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Windows.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Windows.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Windows`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -12,7 +13,5 @@ class SystemWindowsNamespace extends Namespace { /** A class in the `System.Windows` namespace. */ class SystemWindowsClass extends Class { - SystemWindowsClass() { - this.getNamespace() instanceof SystemWindowsNamespace - } + SystemWindowsClass() { this.getNamespace() instanceof SystemWindowsNamespace } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll index cb8c855b020..5fe75994f8e 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Xml`. */ + import csharp private import semmle.code.csharp.frameworks.System @@ -20,9 +21,7 @@ class SystemXmlSchemaNamespace extends Namespace { /** A class in the `System.Xml` namespace. */ class SystemXmlClass extends Class { - SystemXmlClass() { - this.getNamespace() instanceof SystemXmlNamespace - } + SystemXmlClass() { this.getNamespace() instanceof SystemXmlNamespace } } /** The `System.Xml.XmlDocument` class. */ @@ -63,17 +62,12 @@ class SystemXmlXmlReaderSettingsClass extends Class { } /** Gets the `ValidationType` property. */ - Property getValidationTypeProperty() { - result = this.getProperty("ValidationType") - } + Property getValidationTypeProperty() { result = this.getProperty("ValidationType") } /** Gets the `ValidationFlags` property. */ - Property getValidationFlagsProperty() { - result = this.getProperty("ValidationFlags") - } + Property getValidationFlagsProperty() { result = this.getProperty("ValidationFlags") } } - /** The `System.Xml.XmlNode` class. */ class SystemXmlXmlNodeClass extends Class { SystemXmlXmlNodeClass() { @@ -123,35 +117,37 @@ class SystemXmlXmlNamedNodeMapClass extends Class { /** An enum constant in `System.Xml.ValidationType`. */ class SystemXmlValidationType extends EnumConstant { SystemXmlValidationType() { - this.getDeclaringEnum() = any(Enum e | e = any(SystemXmlNamespace n).getAnEnum() and e.hasName("ValidationType")) + this.getDeclaringEnum() = any(Enum e | + e = any(SystemXmlNamespace n).getAnEnum() and e.hasName("ValidationType") + ) } } /** An enum constant in `System.Xml.Schema.XmlSchemaValidationFlags`. */ class SystemXmlSchemaXmlSchemaValidationFlags extends EnumConstant { SystemXmlSchemaXmlSchemaValidationFlags() { - this.getDeclaringEnum() = any(Enum e | e = any(SystemXmlSchemaNamespace s).getAnEnum() and e.hasName("XmlSchemaValidationFlags")) + this.getDeclaringEnum() = any(Enum e | + e = any(SystemXmlSchemaNamespace s).getAnEnum() and e.hasName("XmlSchemaValidationFlags") + ) } } -private Expr getBitwiseOrOperand(Expr e) { - result = e.(BitwiseOrExpr).getAnOperand() -} +private Expr getBitwiseOrOperand(Expr e) { result = e.(BitwiseOrExpr).getAnOperand() } /** A creation of an instance of `System.Xml.XmlReaderSettings`. */ class XmlReaderSettingsCreation extends ObjectCreation { - XmlReaderSettingsCreation() { - this.getType() instanceof SystemXmlXmlReaderSettingsClass - } + XmlReaderSettingsCreation() { this.getType() instanceof SystemXmlXmlReaderSettingsClass } /** Gets a value set on the `ValidationType` property, if any. */ SystemXmlValidationType getValidationType() { - result.getAnAccess() = this.getPropertyValue(any(SystemXmlXmlReaderSettingsClass s).getValidationTypeProperty()) + result.getAnAccess() = this + .getPropertyValue(any(SystemXmlXmlReaderSettingsClass s).getValidationTypeProperty()) } /** Gets a flag set on the `ValidationFlags` property, if any. */ SystemXmlSchemaXmlSchemaValidationFlags getAValidationFlag() { - result.getAnAccess() = this.getPropertyValue(any(SystemXmlXmlReaderSettingsClass s).getValidationFlagsProperty()) + result.getAnAccess() = this + .getPropertyValue(any(SystemXmlXmlReaderSettingsClass s).getValidationFlagsProperty()) } /** Gets a value set for the given property in this local context. */ @@ -167,31 +163,23 @@ class XmlReaderSettingsCreation extends ObjectCreation { } private class SettingsDataFlowConfig extends DataFlow::Configuration { - SettingsDataFlowConfig() { - this = "SettingsDataFlowConfig" - } + SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" } - override - predicate isSource(DataFlow::Node source) { + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof XmlReaderSettingsCreation } - override - predicate isSink(DataFlow::Node sink) { + override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof XmlReaderSettingsInstance } } /** A call to `XmlReader.Create`. */ class XmlReaderCreateCall extends MethodCall { - XmlReaderCreateCall() { - this.getTarget() = any(SystemXmlXmlReaderClass r).getCreateMethod() - } + XmlReaderCreateCall() { this.getTarget() = any(SystemXmlXmlReaderClass r).getCreateMethod() } /** Gets the settings used for this create call, if any. */ - XmlReaderSettingsInstance getSettings() { - result = this.getAnArgument() - } + XmlReaderSettingsInstance getSettings() { result = this.getAnArgument() } } /** An instance of `XmlReaderSettings` passed to an `XmlReader.Create` call. */ diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/codedom/Compiler.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/codedom/Compiler.qll index 6a1da6be873..f6e1e4e4279 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/codedom/Compiler.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/codedom/Compiler.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.CodeDom.Compiler`. */ + import csharp private import semmle.code.csharp.frameworks.system.CodeDom @@ -12,21 +13,15 @@ class SystemCodeDomCompilerNamespace extends Namespace { /** A reference type in the `System.CodeDom.Compiler` namespace. */ class SystemCodeDomCompilerClass extends RefType { - SystemCodeDomCompilerClass() { - this.getNamespace() instanceof SystemCodeDomCompilerNamespace - } + SystemCodeDomCompilerClass() { this.getNamespace() instanceof SystemCodeDomCompilerNamespace } } /** The `System.CodeDom.Compiler.GeneratedCodeAttribute` class. */ class SystemCodeDomCompilerGeneratedCodeAttributeClass extends SystemCodeDomCompilerClass { - SystemCodeDomCompilerGeneratedCodeAttributeClass() { - this.hasName("GeneratedCodeAttribute") - } + SystemCodeDomCompilerGeneratedCodeAttributeClass() { this.hasName("GeneratedCodeAttribute") } } /** The `System.CodeDom.Compiler.ICodeCompiler` class. */ class SystemCodeDomCompilerICodeCompilerClass extends SystemCodeDomCompilerClass { - SystemCodeDomCompilerICodeCompilerClass() { - this.hasName("ICodeCompiler") - } + SystemCodeDomCompilerICodeCompilerClass() { this.hasName("ICodeCompiler") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Generic.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Generic.qll index 17358fbac1d..14a1cb17fc7 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Generic.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Generic.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Collections.Generic`. */ + import csharp private import semmle.code.csharp.frameworks.system.Collections @@ -26,44 +27,30 @@ class SystemCollectionsGenericUnboundGenericStruct extends UnboundGenericStruct /** The `System.Collections.Generic.IComparer` interface. */ class SystemCollectionsGenericIComparerTInterface extends SystemCollectionsGenericUnboundGenericInterface { - SystemCollectionsGenericIComparerTInterface() { - this.hasName("IComparer<>") - } + SystemCollectionsGenericIComparerTInterface() { this.hasName("IComparer<>") } /** Gets the `int Compare(T, T)` method. */ Method getCompareMethod() { - result.getDeclaringType() = this - and - result.hasName("Compare") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() = getTypeParameter(0) - and - result.getParameter(1).getType() = getTypeParameter(0) - and + result.getDeclaringType() = this and + result.hasName("Compare") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() = getTypeParameter(0) and + result.getParameter(1).getType() = getTypeParameter(0) and result.getReturnType() instanceof IntType } } /** The `System.Collections.Generic.IEqualityComparer` interface. */ class SystemCollectionsGenericIEqualityComparerTInterface extends SystemCollectionsGenericUnboundGenericInterface { - SystemCollectionsGenericIEqualityComparerTInterface() { - this.hasName("IEqualityComparer<>") - } + SystemCollectionsGenericIEqualityComparerTInterface() { this.hasName("IEqualityComparer<>") } /** Gets the `bool Equals(T, T)` method. */ Method getEqualsMethod() { - result.getDeclaringType() = this - and - result.hasName("Equals") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() = getTypeParameter(0) - and - result.getParameter(1).getType() = getTypeParameter(0) - and + result.getDeclaringType() = this and + result.hasName("Equals") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() = getTypeParameter(0) and + result.getParameter(1).getType() = getTypeParameter(0) and result.getReturnType() instanceof BoolType } } @@ -71,8 +58,7 @@ class SystemCollectionsGenericIEqualityComparerTInterface extends SystemCollecti /** The `System.Collections.Generic.IEnumerable` interface. */ class SystemCollectionsGenericIEnumerableTInterface extends SystemCollectionsGenericUnboundGenericInterface { SystemCollectionsGenericIEnumerableTInterface() { - this.hasName("IEnumerable<>") - and + this.hasName("IEnumerable<>") and this.getNumberOfTypeParameters() = 1 } } @@ -80,17 +66,14 @@ class SystemCollectionsGenericIEnumerableTInterface extends SystemCollectionsGen /** The `System.Collections.Generic.IEnumerator` interface. */ class SystemCollectionsGenericIEnumeratorInterface extends SystemCollectionsGenericUnboundGenericInterface { SystemCollectionsGenericIEnumeratorInterface() { - this.hasName("IEnumerator<>") - and + this.hasName("IEnumerator<>") and this.getNumberOfTypeParameters() = 1 } /** Gets the `Current` property. */ Property getCurrentProperty() { - result.getDeclaringType() = this - and - result.hasName("Current") - and + result.getDeclaringType() = this and + result.hasName("Current") and result.getType() = this.getTypeParameter(0) } } @@ -98,8 +81,7 @@ class SystemCollectionsGenericIEnumeratorInterface extends SystemCollectionsGene /** The `System.Collections.Generic.IList` interface. */ class SystemCollectionsGenericIListTInterface extends SystemCollectionsGenericUnboundGenericInterface { SystemCollectionsGenericIListTInterface() { - this.hasName("IList<>") - and + this.hasName("IList<>") and this.getNumberOfTypeParameters() = 1 } } @@ -107,33 +89,26 @@ class SystemCollectionsGenericIListTInterface extends SystemCollectionsGenericUn /** The `System.Collections.Generic.KeyValuePair` structure. */ class SystemCollectionsGenericKeyValuePairStruct extends SystemCollectionsGenericUnboundGenericStruct { SystemCollectionsGenericKeyValuePairStruct() { - this.hasName("KeyValuePair<,>") - and + this.hasName("KeyValuePair<,>") and this.getNumberOfTypeParameters() = 2 } /** Gets the `Key` property. */ Property getKeyProperty() { - result.getDeclaringType() = this - and - result.hasName("Key") - and + result.getDeclaringType() = this and + result.hasName("Key") and result.getType() = this.getTypeParameter(0) } /** Gets the `Value` property. */ Property getValueProperty() { - result.getDeclaringType() = this - and - result.hasName("Value") - and + result.getDeclaringType() = this and + result.hasName("Value") and result.getType() = this.getTypeParameter(1) } } /** The `System.Collections.Generic.ICollection<>` interface. */ class SystemCollectionsGenericICollectionInterface extends SystemCollectionsGenericUnboundGenericInterface { - SystemCollectionsGenericICollectionInterface() { - this.hasName("ICollection<>") - } + SystemCollectionsGenericICollectionInterface() { this.hasName("ICollection<>") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Specialized.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Specialized.qll index 4d36a558ea5..2ddac761c4b 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Specialized.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/collections/Specialized.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Collections.Specialized`. */ + import csharp private import semmle.code.csharp.frameworks.system.Collections @@ -19,7 +20,5 @@ class SystemCollectionsSpecializedClass extends Class { /** The `System.Collections.Specialized.NameValueCollection` class. */ class SystemCollectionsSpecializedNameValueCollectionClass extends SystemCollectionsSpecializedClass { - SystemCollectionsSpecializedNameValueCollectionClass() { - this.hasName("NameValueCollection") - } + SystemCollectionsSpecializedNameValueCollectionClass() { this.hasName("NameValueCollection") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Common.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Common.qll index ec9e49f0f6b..ed70797ff12 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Common.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Common.qll @@ -1,11 +1,11 @@ /** * Provides classes related to the namespace `System.Data.Common`. */ + private import csharp as csharp private import semmle.code.csharp.frameworks.system.Data as Data module SystemDataCommon { - /** The `System.Data.Common` namespace. */ class Namespace extends csharp::Namespace { Namespace() { @@ -15,21 +15,11 @@ module SystemDataCommon { } /** A class in the `System.Data.Common` namespace. */ - class Class extends csharp::Class { - Class() { - this.getNamespace() instanceof Namespace - } - } + class Class extends csharp::Class { Class() { this.getNamespace() instanceof Namespace } } /** The `System.Data.Common.DbDataReader` class. */ - class DbDataReader extends Class { - DbDataReader() { - this.hasName("DbDataReader") - } - } + class DbDataReader extends Class { DbDataReader() { this.hasName("DbDataReader") } } /** The `System.Data.Common.DbException` class. */ - class DbException extends Class { - DbException() { this.hasName("DbException") } - } + class DbException extends Class { DbException() { this.hasName("DbException") } } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll index 1d49bccab08..23b62202a09 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/Entity.qll @@ -1,11 +1,11 @@ /** * Provides classes related to the Entity Framework namespace `System.Data.Entity`. */ + private import csharp as csharp private import semmle.code.csharp.frameworks.system.Data as Data module SystemDataEntity { - /** The `System.Data.Entity` namespace. */ class Namespace extends csharp::Namespace { Namespace() { @@ -15,22 +15,14 @@ module SystemDataEntity { } /** A class in the `System.Data.Entity` namespace. */ - class Class extends csharp::Class { - Class() { - this.getNamespace() instanceof Namespace - } - } + class Class extends csharp::Class { Class() { this.getNamespace() instanceof Namespace } } /** The `System.Data.Entity.DbSet` class. */ class Database extends Class { - Database() { - this.hasName("Database") - } + Database() { this.hasName("Database") } /** Gets the `ExecuteSqlCommand` method. */ - csharp::Method getExecuteSqlCommandMethod() { - result = this.getAMethod("ExecuteSqlCommand") - } + csharp::Method getExecuteSqlCommandMethod() { result = this.getAMethod("ExecuteSqlCommand") } /** Gets the `ExecuteSqlCommandAsync` method. */ csharp::Method getExecuteSqlCommandAsyncMethod() { @@ -38,9 +30,7 @@ module SystemDataEntity { } /** Gets the `SqlQuery` method. */ - csharp::Method getSqlQueryMethod() { - result = this.getAMethod("SqlQuery") - } + csharp::Method getSqlQueryMethod() { result = this.getAMethod("SqlQuery") } } /** The `System.Data.Entity.DbSet` class. */ @@ -50,22 +40,14 @@ module SystemDataEntity { } /** Gets the `SqlQuery` method. */ - csharp::Method getSqlQueryMethod() { - result = this.getAMethod("SqlQuery") - } + csharp::Method getSqlQueryMethod() { result = this.getAMethod("SqlQuery") } /** Gets the `DbSet` type, if any. */ - csharp::Type getDbSetType() { - result = this.(csharp::ConstructedType).getTypeArgument(0) - } + csharp::Type getDbSetType() { result = this.(csharp::ConstructedType).getTypeArgument(0) } } /** The `System.Data.Entity.DbContext` class. */ - class DbContext extends Class { - DbContext() { - this.hasName("DbContext") - } - } + class DbContext extends Class { DbContext() { this.hasName("DbContext") } } /** A user provided sub type of `DbContext`. */ class CustomDbContext extends csharp::Class { @@ -102,16 +84,16 @@ module SystemDataEntityInfrastructure { } /** A class in the `System.Data.Entity.Infrastructure` namespace. */ - class Class extends csharp::Class { - Class() { - this.getNamespace() instanceof Namespace - } - } + class Class extends csharp::Class { Class() { this.getNamespace() instanceof Namespace } } /** A class that extends or is constructed from `System.Entity.Data.Infrastructure.DbRawSqlQuery`. */ class DbRawSqlQuery extends Class { DbRawSqlQuery() { - this.getABaseType*().getSourceDeclaration().(csharp::UnboundGenericClass).getNameWithoutBrackets() = "DbRawSqlQuery" + this + .getABaseType*() + .getSourceDeclaration() + .(csharp::UnboundGenericClass) + .getNameWithoutBrackets() = "DbRawSqlQuery" } } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlClient.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlClient.qll index 8961aad8f61..858100fe7f7 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlClient.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlClient.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Data.SqlClient`. */ + import csharp private import semmle.code.csharp.frameworks.system.Data @@ -12,9 +13,7 @@ class SystemDataSqlClientNamespace extends Namespace { /** A class in the `System.Data.SqlClient` namespace. */ class SystemDataSqlClientClass extends Class { - SystemDataSqlClientClass() { - getNamespace() instanceof SystemDataSqlClientNamespace - } + SystemDataSqlClientClass() { getNamespace() instanceof SystemDataSqlClientNamespace } } /** The `System.Data.SqlClient.SqlDataAdapter` class. */ @@ -26,7 +25,5 @@ class SystemDataSqlClientSqlDataAdapterClass extends SystemDataSqlClientClass { /** The `System.Data.SqlClient.SqlConnection` class. */ class SystemDataSqlClientSqlConnectionClass extends SystemDataSqlClientClass { - SystemDataSqlClientSqlConnectionClass() { - this.hasName("SqlConnection") - } + SystemDataSqlClientSqlConnectionClass() { this.hasName("SqlConnection") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlServerCe.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlServerCe.qll index 703598db256..4ed6b930fba 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlServerCe.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/data/SqlServerCe.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Data.SqlServerCe`. */ + import csharp private import semmle.code.csharp.frameworks.system.Data @@ -12,14 +13,10 @@ class SystemDataSqlServerCeNamespace extends Namespace { /** A class in the `System.Data.SqlServerCe` namespace. */ class SystemDataSqlServerCeClass extends Class { - SystemDataSqlServerCeClass() { - this.getNamespace() instanceof SystemDataSqlServerCeNamespace - } + SystemDataSqlServerCeClass() { this.getNamespace() instanceof SystemDataSqlServerCeNamespace } } /** The `System.Data.SqlServerCe.SqlCeConnection` class. */ class SystemDataSqlServerCeSqlCeConnectionClass extends SystemDataSqlServerCeClass { - SystemDataSqlServerCeSqlCeConnectionClass() { - this.hasName("SqlCeConnection") - } + SystemDataSqlServerCeSqlCeConnectionClass() { this.hasName("SqlCeConnection") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/directoryservices/Protocols.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/directoryservices/Protocols.qll index 33b7680ff95..033cf865adf 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/directoryservices/Protocols.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/directoryservices/Protocols.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.DirectoryServices.Protocols`. */ + import csharp private import semmle.code.csharp.frameworks.system.DirectoryServices @@ -19,7 +20,5 @@ class SystemDirectoryServicesProtocolsClass extends Class { /** The `System.DirectoryServices.Protocols.SearchRequest` class. */ class SystemDirectoryServicesProtocolsSearchRequest extends SystemDirectoryServicesProtocolsClass { - SystemDirectoryServicesProtocolsSearchRequest() { - this.hasName("SearchRequest") - } + SystemDirectoryServicesProtocolsSearchRequest() { this.hasName("SearchRequest") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/io/Compression.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/io/Compression.qll index 14b42dadf10..b1b777b0f69 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/io/Compression.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/io/Compression.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.IO.Compression`. */ + import csharp private import semmle.code.csharp.frameworks.system.IO @@ -12,9 +13,7 @@ class SystemIOCompressionNamespace extends Namespace { /** A class in the `System.IO.Compression` namespace. */ class SystemIOCompressionClass extends Class { - SystemIOCompressionClass() { - this.getNamespace() instanceof SystemIOCompressionNamespace - } + SystemIOCompressionClass() { this.getNamespace() instanceof SystemIOCompressionNamespace } } /** The `System.IO.Compression.DeflateStream` class. */ diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/linq/Expressions.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/linq/Expressions.qll index 41897e8320c..5a2cf7e17ab 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/linq/Expressions.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/linq/Expressions.qll @@ -1,11 +1,11 @@ /** * Provides classes related to the namespace `System.Linq.Expressions`. */ + private import csharp as csharp private import semmle.code.csharp.frameworks.system.Linq module SystemLinqExpressions { - /** The `System.Linq.Expressions` namespace. */ class Namespace extends csharp::Namespace { Namespace() { @@ -15,17 +15,11 @@ module SystemLinqExpressions { } /** A class in the `System.Linq.Expressions` namespace. */ - class Class extends csharp::Class { - Class() { - this.getNamespace() instanceof Namespace - } - } + class Class extends csharp::Class { Class() { this.getNamespace() instanceof Namespace } } /** The `Expression` class. */ class ExpressionDelegate extends Class, csharp::UnboundGenericClass { - ExpressionDelegate() { - this.hasName("Expression<>") - } + ExpressionDelegate() { this.hasName("Expression<>") } } /** @@ -40,14 +34,12 @@ module SystemLinqExpressions { this = dt or this = any(csharp::ConstructedClass cc | - cc.getUnboundGeneric() instanceof ExpressionDelegate and - dt = cc.getTypeArgument(0) - ) + cc.getUnboundGeneric() instanceof ExpressionDelegate and + dt = cc.getTypeArgument(0) + ) } /** Gets the underlying `delegate` type. */ - csharp::DelegateType getDelegateType() { - result = dt - } + csharp::DelegateType getDelegateType() { result = dt } } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/net/Mail.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/net/Mail.qll index ae6f059ebc5..631a09058a3 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/net/Mail.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/net/Mail.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Net.Mail`. */ + import csharp private import semmle.code.csharp.frameworks.system.Net @@ -12,17 +13,12 @@ class SystemNetMailNamespace extends Namespace { /** A class in the `System.Net.Mail` namespace. */ class SystemNetMailClass extends Class { - SystemNetMailClass() { - this.getNamespace() instanceof SystemNetMailNamespace - } + SystemNetMailClass() { this.getNamespace() instanceof SystemNetMailNamespace } } - /** The class `System.Net.Mail.MailMessage`. */ class SystemNetMailMailMessageClass extends SystemNetMailClass { - SystemNetMailMailMessageClass() { - this.hasName("MailMessage") - } + SystemNetMailMailMessageClass() { this.hasName("MailMessage") } /** Gets the `Body` property. */ Property getBodyProperty() { result = this.getProperty("Body") } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/InteropServices.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/InteropServices.qll index 48b55e97324..e619f8dce8d 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/InteropServices.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/runtime/InteropServices.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Runtime.InteropServices`. */ + import csharp private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.frameworks.system.Runtime @@ -20,51 +21,35 @@ class SystemRuntimeInteropServicesClass extends Class { /** The `System.Runtime.InteropServices.DllImportAttribute` class. */ class SystemRuntimeInteropServicesDllImportAttributeClass extends SystemRuntimeInteropServicesClass { - SystemRuntimeInteropServicesDllImportAttributeClass() { - this.hasName("DllImportAttribute") - } + SystemRuntimeInteropServicesDllImportAttributeClass() { this.hasName("DllImportAttribute") } } /** The `System.Runtime.InteropServices.Marshal` class. */ class SystemRuntimeInteropServicesMarshalClass extends SystemRuntimeInteropServicesClass { - SystemRuntimeInteropServicesMarshalClass() { - this.hasName("Marshal") - } + SystemRuntimeInteropServicesMarshalClass() { this.hasName("Marshal") } /** Gets the `PtrToStructure(IntPtr, Type)` method. */ Method getPtrToStructureTypeMethod() { - result.getDeclaringType()=this - and - result.hasName("PtrToStructure") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof SystemIntPtrType - and - result.getParameter(1).getType() instanceof SystemTypeClass - and + result.getDeclaringType() = this and + result.hasName("PtrToStructure") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof SystemIntPtrType and + result.getParameter(1).getType() instanceof SystemTypeClass and result.getReturnType() instanceof SystemObjectClass } /** Gets the `PtrToStructure(IntPtr, object)` method. */ Method getPtrToStructureObjectMethod() { - result.getDeclaringType()=this - and - result.hasName("PtrToStructure") - and - result.getNumberOfParameters() = 2 - and - result.getParameter(0).getType() instanceof SystemIntPtrType - and - result.getParameter(1).getType() instanceof SystemObjectClass - and + result.getDeclaringType() = this and + result.hasName("PtrToStructure") and + result.getNumberOfParameters() = 2 and + result.getParameter(0).getType() instanceof SystemIntPtrType and + result.getParameter(1).getType() instanceof SystemObjectClass and result.getReturnType() instanceof VoidType } } /** The `System.Runtime.InteropServices.ComImportAttribute` class. */ class SystemRuntimeInteropServicesComImportAttributeClass extends SystemRuntimeInteropServicesClass { - SystemRuntimeInteropServicesComImportAttributeClass() { - this.hasName("ComImportAttribute") - } + SystemRuntimeInteropServicesComImportAttributeClass() { this.hasName("ComImportAttribute") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/security/Cryptography.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/security/Cryptography.qll index 96e443f2c08..40c07eef121 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/security/Cryptography.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/security/Cryptography.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Security.Cryptography`. */ + import csharp private import semmle.code.csharp.frameworks.system.Security diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll index 6ac3e64cc17..54cc8d11864 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Security.Cryptography.X509Certificates`. */ + import csharp private import semmle.code.csharp.frameworks.system.security.Cryptography diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll index 6ee0167c4fb..0914499fd0d 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/text/RegularExpressions.qll @@ -18,19 +18,13 @@ class SystemTextRegularExpressionsClass extends Class { /** The `System.Text.RegularExpressions.Regex` class. */ class SystemTextRegularExpressionsRegexClass extends SystemTextRegularExpressionsClass { - SystemTextRegularExpressionsRegexClass() { - this.hasName("Regex") - } + SystemTextRegularExpressionsRegexClass() { this.hasName("Regex") } /** Gets a `Replace` method. */ - Method getAReplaceMethod() { - result = this.getAMethod("Replace") - } + Method getAReplaceMethod() { result = this.getAMethod("Replace") } /** Gets a `Match` method. */ - Method getAMatchMethod() { - result = this.getAMethod("Match") - } + Method getAMatchMethod() { result = this.getAMethod("Match") } } /** @@ -48,20 +42,17 @@ class RegexGlobalTimeout extends MethodCall { */ class RegexOperation extends Call { Expr pattern; + RegexOperation() { this.getTarget() = any(SystemTextRegularExpressionsRegexClass r).getAMember() and pattern = this.getArgumentForName("pattern") } /** Gets the `pattern` argument. */ - Expr getPattern() { - result = pattern - } + Expr getPattern() { result = pattern } /** Holds if this regular expression has a timeout. */ - predicate hasTimeout() { - exists(this.getArgumentForName("matchTimeout")) - } + predicate hasTimeout() { exists(this.getArgumentForName("matchTimeout")) } /** * Gets an `input` argument used with this regex. @@ -71,15 +62,17 @@ class RegexOperation extends Call { * the `Regex` is declared in a field. */ Expr getInput() { - if this instanceof MethodCall then - result = getArgumentForName("input") + if this instanceof MethodCall + then result = getArgumentForName("input") else exists(MethodCall call | call.getTarget() = any(SystemTextRegularExpressionsRegexClass rs).getAMethod() and - result = call.getArgumentForName("input") | + result = call.getArgumentForName("input") + | // e.g. `new Regex(...).Match(...)` // or `var r = new Regex(...); r.Match(...)` - DataFlow::localFlow(DataFlow::exprNode(this), DataFlow::exprNode(call.getQualifier())) or + DataFlow::localFlow(DataFlow::exprNode(this), DataFlow::exprNode(call.getQualifier())) + or // e.g. `private string r = new Regex(...); public void foo() { r.Match(...); }` call.getQualifier().(FieldAccess).getTarget().getInitializer() = this ) diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll index 2e5e4739afd..808ce188aac 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/threading/Tasks.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Threading.Tasks`. */ + import csharp private import semmle.code.csharp.frameworks.system.Threading @@ -12,9 +13,7 @@ class SystemThreadingTasksNamespace extends Namespace { /** A class in the `System.Threading.Tasks` namespace. */ class SystemThreadingTasksClass extends Class { - SystemThreadingTasksClass() { - this.getNamespace() instanceof SystemThreadingTasksNamespace - } + SystemThreadingTasksClass() { this.getNamespace() instanceof SystemThreadingTasksNamespace } } /** An unbound generic class in the `System.Threading.Tasks` namespace. */ @@ -26,23 +25,17 @@ class SystemThreadingTasksUnboundGenericClass extends UnboundGenericClass { /** The `System.Threading.Tasks.Task` class. */ class SystemThreadingTasksTaskClass extends SystemThreadingTasksClass { - SystemThreadingTasksTaskClass() { - this.hasName("Task") - } + SystemThreadingTasksTaskClass() { this.hasName("Task") } } /** The `System.Threading.Tasks.Task` class. */ class SystemThreadingTasksTaskTClass extends SystemThreadingTasksUnboundGenericClass { - SystemThreadingTasksTaskTClass() { - this.hasName("Task<>") - } + SystemThreadingTasksTaskTClass() { this.hasName("Task<>") } /** Gets the `Result` property. */ Property getResultProperty() { - result.getDeclaringType() = this - and - result.hasName("Result") - and + result.getDeclaringType() = this and + result.hasName("Result") and result.getType() = this.getTypeParameter(0) } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Helpers.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Helpers.qll index cb941cf7eff..6fca5cda851 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Helpers.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Helpers.qll @@ -1,12 +1,11 @@ /** Provides definitions related to the namespace `System.Web.Helpers`. */ + import csharp import semmle.code.csharp.frameworks.system.Web /** The `System.Web.Helpers` namespace. */ class SystemWebHelpersNamespace extends Namespace { - SystemWebHelpersNamespace() { - this.hasName("Helpers") - } + SystemWebHelpersNamespace() { this.hasName("Helpers") } } /** The `System.Web.Helpers.AntiForgery` class. */ @@ -17,7 +16,5 @@ class AntiForgeryClass extends Class { } /** Gets the `Validate` method. */ - Method getValidateMethod() { - result = this.getAMethod("Validate") - } + Method getValidateMethod() { result = this.getAMethod("Validate") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Http.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Http.qll index d6fb18796e8..0057510ebe3 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Http.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Http.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Web.Http`. */ + import csharp private import semmle.code.csharp.frameworks.system.Web @@ -12,44 +13,32 @@ class SystemWebHttpNamespace extends Namespace { /** A class in the `System.Web.Http` namespace. */ class SystemWebHttpClass extends Class { - SystemWebHttpClass() { - this.getNamespace() instanceof SystemWebHttpNamespace - } + SystemWebHttpClass() { this.getNamespace() instanceof SystemWebHttpNamespace } } /** An interface in the `System.Web.Http` namespace. */ class SystemWebHttpInterface extends Interface { - SystemWebHttpInterface() { - this.getNamespace() instanceof SystemWebHttpNamespace - } + SystemWebHttpInterface() { this.getNamespace() instanceof SystemWebHttpNamespace } } /** An attribute whose type is in the `System.Web.Http` namespace. */ class SystemWebHttpAttribute extends Attribute { - SystemWebHttpAttribute() { - this.getType().getNamespace() instanceof SystemWebHttpNamespace - } + SystemWebHttpAttribute() { this.getType().getNamespace() instanceof SystemWebHttpNamespace } } /** An attribute whose type is `System.Web.Http.NonAction`. */ class SystemWebHttpNonActionAttribute extends SystemWebHttpAttribute { - SystemWebHttpNonActionAttribute() { - this.getType().hasName("NonActionAttribute") - } + SystemWebHttpNonActionAttribute() { this.getType().hasName("NonActionAttribute") } } /** The `System.Web.Http.ApiController` class. */ class SystemWebHttpApiControllerClass extends SystemWebHttpClass { - SystemWebHttpApiControllerClass() { - this.hasName("ApiController") - } + SystemWebHttpApiControllerClass() { this.hasName("ApiController") } } /** A subtype of `System.Web.Http.ApiController`. */ class ApiController extends Class { - ApiController() { - this.getABaseType*() instanceof SystemWebHttpApiControllerClass - } + ApiController() { this.getABaseType*() instanceof SystemWebHttpApiControllerClass } /** Gets an action method for this controller. */ Method getAnActionMethod() { @@ -65,7 +54,8 @@ class ApiController extends Class { * Holds if this expression is a constant that evaluates to the name of an IIS server variable. */ predicate isServerVariable(Expr e) { - exists(string s | s = e.getValue() and + exists(string s | + s = e.getValue() and ( s = "ALL_HTTP" or s = "ALL_RAW" or @@ -127,7 +117,7 @@ predicate isServerVariable(Expr e) { s = "SERVER_SOFTWARE" or s = "SSI_EXEC_DISABLED" or s = "UNENCODED_URL" or - s.matches("UNICODE\\_%") or // UNICODE_ + s.matches("UNICODE\\_%") or // UNICODE_ s = "UNMAPPED_REMOTE_USER" or s = "URL" or s = "URL_PATH_INFO" diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Mvc.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Mvc.qll index 677b9559d96..78aaa6dc065 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Mvc.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Mvc.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Web.Mvc`. */ + import csharp private import semmle.code.csharp.frameworks.system.Web @@ -12,49 +13,35 @@ class SystemWebMvcNamespace extends Namespace { /** A class in the `System.Web.Mvc` namespace. */ class SystemWebMvcClass extends Class { - SystemWebMvcClass() { - this.getNamespace() instanceof SystemWebMvcNamespace - } + SystemWebMvcClass() { this.getNamespace() instanceof SystemWebMvcNamespace } } /** An interface in the `System.Web.Mvc` namespace. */ class SystemWebMvcInterface extends Interface { - SystemWebMvcInterface() { - this.getNamespace() instanceof SystemWebMvcNamespace - } + SystemWebMvcInterface() { this.getNamespace() instanceof SystemWebMvcNamespace } } /** The `System.Web.Mvc.HtmlHelper` class. */ class SystemWebMvcHtmlHelperClass extends SystemWebMvcClass { - SystemWebMvcHtmlHelperClass() { - this.hasName("HtmlHelper") - } + SystemWebMvcHtmlHelperClass() { this.hasName("HtmlHelper") } /** Gets the `Raw` method. */ - Method getRawMethod() { - result = this.getAMethod("Raw") - } + Method getRawMethod() { result = this.getAMethod("Raw") } } /** An attribute whose type is in the `System.Web.Mvc` namespace. */ class SystemWebMvcAttribute extends Attribute { - SystemWebMvcAttribute() { - getType().getNamespace() instanceof SystemWebMvcNamespace - } + SystemWebMvcAttribute() { getType().getNamespace() instanceof SystemWebMvcNamespace } } /** An attribute whose type is `System.Web.Mvc.HttpPost`. */ class HttpPostAttribute extends SystemWebMvcAttribute { - HttpPostAttribute() { - this.getType().hasName("HttpPostAttribute") - } + HttpPostAttribute() { this.getType().hasName("HttpPostAttribute") } } /** An attribute whose type is `System.Web.Mvc.NonAction`. */ class NonActionAttribute extends SystemWebMvcAttribute { - NonActionAttribute() { - this.getType().hasName("NonActionAttribute") - } + NonActionAttribute() { this.getType().hasName("NonActionAttribute") } } /** @@ -68,21 +55,15 @@ class ValidateAntiForgeryTokenAttribute extends Attribute { /** The `System.Web.Mvc.UrlHelper` class. */ class SystemWebMvcUrlHelperClass extends SystemWebMvcClass { - SystemWebMvcUrlHelperClass() { - this.hasName("UrlHelper") - } + SystemWebMvcUrlHelperClass() { this.hasName("UrlHelper") } /** Gets the `IsLocalUrl` method. */ - Method getIsLocalUrl() { - result = this.getAMethod("IsLocalUrl") - } + Method getIsLocalUrl() { result = this.getAMethod("IsLocalUrl") } } /** The `System.Web.Mvc.Controller` class. */ class SystemWebMvcControllerClass extends SystemWebMvcClass { - SystemWebMvcControllerClass() { - this.hasName("Controller") - } + SystemWebMvcControllerClass() { this.hasName("Controller") } /** Gets a `Redirect..` method. */ Method getARedirectMethod() { @@ -93,9 +74,7 @@ class SystemWebMvcControllerClass extends SystemWebMvcClass { /** A subtype of `System.Web.Mvc.Controller`. */ class Controller extends Class { - Controller() { - this.getABaseType*() instanceof SystemWebMvcControllerClass - } + Controller() { this.getABaseType*() instanceof SystemWebMvcControllerClass } /** * Gets an "action" method, which may be called by the MVC framework in response to a user @@ -126,26 +105,18 @@ class AuthorizationFilter extends Class { } /** Gets the `OnAuthorization` method provided by this filter. */ - Method getOnAuthorizationMethod() { - result = this.getAMethod("OnAuthorization") - } + Method getOnAuthorizationMethod() { result = this.getAMethod("OnAuthorization") } } /** The `System.Web.Mvc.GlobalFilterCollection` class. */ class GlobalFilterCollection extends SystemWebMvcClass { - GlobalFilterCollection() { - this.hasName("GlobalFilterCollection") - } + GlobalFilterCollection() { this.hasName("GlobalFilterCollection") } /** Gets the `Add` method. */ - Method getAddMethod() { - result = this.getAMethod("Add") - } + Method getAddMethod() { result = this.getAMethod("Add") } } /** The `System.Web.Mvc.MvcHtmlString` class. */ class SystemWebMvcMvcHtmlString extends SystemWebMvcClass { - SystemWebMvcMvcHtmlString() { - this.hasName("MvcHtmlString") - } + SystemWebMvcMvcHtmlString() { this.hasName("MvcHtmlString") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Security.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Security.qll index 68ba4419bb1..9f4e68b6111 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Security.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Security.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Web.Security`. */ + import csharp private import semmle.code.csharp.frameworks.system.Web @@ -12,23 +13,17 @@ class SystemWebSecurityNamespace extends Namespace { /** A class in the `System.Web.Security` namespace. */ class SystemWebSecurityClass extends Class { - SystemWebSecurityClass() { - this.getNamespace() instanceof SystemWebSecurityNamespace - } + SystemWebSecurityClass() { this.getNamespace() instanceof SystemWebSecurityNamespace } } /** The `System.Web.Security.MembershipUser` class. */ class SystemWebSecurityMembershipUserClass extends SystemWebSecurityClass { - SystemWebSecurityMembershipUserClass() { - this.hasName("MembershipUser") - } + SystemWebSecurityMembershipUserClass() { this.hasName("MembershipUser") } } /** The `System.Web.Security.Membership` class. */ class SystemWebSecurityMembershipClass extends SystemWebSecurityClass { - SystemWebSecurityMembershipClass() { - this.hasName("Membership") - } + SystemWebSecurityMembershipClass() { this.hasName("Membership") } /** Gets the `ValidateUser` method. */ Method getValidateUserMethod() { result = this.getAMethod("ValidateUser") } @@ -36,9 +31,7 @@ class SystemWebSecurityMembershipClass extends SystemWebSecurityClass { /** The `System.Web.Security.FormsAuthentication` class. */ class SystemWebSecurityFormsAuthenticationClass extends SystemWebSecurityClass { - SystemWebSecurityFormsAuthenticationClass() { - this.hasName("FormsAuthentication") - } + SystemWebSecurityFormsAuthenticationClass() { this.hasName("FormsAuthentication") } /** Gets the `Authenticate` method. */ Method getAuthenticateMethod() { result = this.getAMethod("Authenticate") } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Services.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Services.qll index 21bc2c269ad..f18b0cb4938 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Services.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/Services.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Web.Services`. */ + import csharp private import semmle.code.csharp.frameworks.system.Web @@ -12,14 +13,10 @@ class SystemWebServicesNamespace extends Namespace { /** A class in the `System.Web.Services` namespace. */ class SystemWebServicesClass extends Class { - SystemWebServicesClass() { - this.getNamespace() instanceof SystemWebServicesNamespace - } + SystemWebServicesClass() { this.getNamespace() instanceof SystemWebServicesNamespace } } /** The `System.Web.Services.WebMethodAttribute` class. */ class SystemWebServicesWebMethodAttributeClass extends SystemWebServicesClass { - SystemWebServicesWebMethodAttributeClass() { - this.hasName("WebMethodAttribute") - } + SystemWebServicesWebMethodAttributeClass() { this.hasName("WebMethodAttribute") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/UI.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/UI.qll index ff1627e6b83..3cb1c59aeed 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/UI.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/UI.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Web.UI`. */ + import csharp private import semmle.code.csharp.frameworks.system.Web @@ -12,23 +13,17 @@ class SystemWebUINamespace extends Namespace { /** A class in the `System.Web.UI` namespace. */ class SystemWebUIClass extends Class { - SystemWebUIClass() { - this.getNamespace() instanceof SystemWebUINamespace - } + SystemWebUIClass() { this.getNamespace() instanceof SystemWebUINamespace } } /** The `System.Web.UI.Control` class. */ class SystemWebUIControlClass extends SystemWebUIClass { - SystemWebUIControlClass() { - this.hasName("Control") - } + SystemWebUIControlClass() { this.hasName("Control") } } /** The `System.Web.UI.Page` class. */ class SystemWebUIPageClass extends SystemWebUIClass { - SystemWebUIPageClass() { - this.hasName("Page") - } + SystemWebUIPageClass() { this.hasName("Page") } /** Get the `ID` property. */ Property getIDProperty() { @@ -54,7 +49,7 @@ class SystemWebUIPageClass extends SystemWebUIClass { result.hasName("Title") } - /** Get the `RegisterStartupScript` method. */ + /** Get the `RegisterStartupScript` method. */ Method getRegisterStartupScriptMethod() { result.getDeclaringType() = this and result.hasName("RegisterStartupScript") @@ -69,9 +64,7 @@ class SystemWebUIPageClass extends SystemWebUIClass { /** The `System.Web.UI.HtmlTextWriter` class. */ class SystemWebUIHtmlTextWriterClass extends SystemWebUIClass { - SystemWebUIHtmlTextWriterClass() { - this.hasName("HtmlTextWriter") - } + SystemWebUIHtmlTextWriterClass() { this.hasName("HtmlTextWriter") } /** Get a `Write` method. */ Method getAWriteMethod() { @@ -106,9 +99,7 @@ class SystemWebUIHtmlTextWriterClass extends SystemWebUIClass { /** The `System.Web.UI.AttributeCollection` class. */ class SystemWebUIAttributeCollectionClass extends SystemWebUIClass { - SystemWebUIAttributeCollectionClass() { - this.hasName("AttributeCollection") - } + SystemWebUIAttributeCollectionClass() { this.hasName("AttributeCollection") } /** Get the `Add` method. */ Method getAddMethod() { @@ -125,11 +116,9 @@ class SystemWebUIAttributeCollectionClass extends SystemWebUIClass { /** The `System.Web.UI.ClientScriptManager` class. */ class SystemWebUIClientScriptManagerClass extends SystemWebUIClass { - SystemWebUIClientScriptManagerClass() { - this.hasName("ClientScriptManager") - } + SystemWebUIClientScriptManagerClass() { this.hasName("ClientScriptManager") } - /** Get the `RegisterStartupScript` method. */ + /** Get the `RegisterStartupScript` method. */ Method getRegisterStartupScriptMethod() { result.getDeclaringType() = this and result.hasName("RegisterStartupScript") diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll index 04e61696706..0d43f76719b 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/WebPages.qll @@ -1,6 +1,6 @@ /** Definitions related to the namespace `System.Web.WebPages`, ASP.NET */ -import csharp +import csharp private import semmle.code.csharp.frameworks.system.Web /** The `System.Web.WebPages` namespace. */ @@ -21,17 +21,11 @@ class SystemWebWebPagesWebPageExecutingBaseClass extends Class { /** A class that derives from `System.Web.WebPages.WebPageExecutingBase`. */ class WebPageClass extends Class { - WebPageClass () { - this.getBaseClass*() instanceof SystemWebWebPagesWebPageExecutingBaseClass - } + WebPageClass() { this.getBaseClass*() instanceof SystemWebWebPagesWebPageExecutingBaseClass } /** Gets the `WriteLiteral` method. */ - Method getWriteLiteralMethod() { - result = getAMethod("WriteLiteral") - } + Method getWriteLiteralMethod() { result = getAMethod("WriteLiteral") } /** Gets the `WriteLiteralTo` method. */ - Method getWriteLiteralToMethod() { - result = getAMethod("WriteLiteralTo") - } + Method getWriteLiteralToMethod() { result = getAMethod("WriteLiteralTo") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/ui/WebControls.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/ui/WebControls.qll index 5dad4dc72bd..a059d5b3c7c 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/web/ui/WebControls.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/web/ui/WebControls.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Web.UI.WebControls`. */ + import csharp private import semmle.code.csharp.frameworks.system.web.UI @@ -12,39 +13,29 @@ class SystemWebUIWebControlsNamespace extends Namespace { /** A class in the `System.Web.UI.WebControls` namespace. */ class SystemWebUIWebControlsClass extends Class { - SystemWebUIWebControlsClass() { - this.getNamespace() instanceof SystemWebUIWebControlsNamespace - } + SystemWebUIWebControlsClass() { this.getNamespace() instanceof SystemWebUIWebControlsNamespace } } /** The `System.Web.UI.WebControls.TextBox` class. */ class SystemWebUIWebControlsTextBoxClass extends SystemWebUIWebControlsClass { - SystemWebUIWebControlsTextBoxClass() { - this.hasName("TextBox") - } + SystemWebUIWebControlsTextBoxClass() { this.hasName("TextBox") } /** Gets the `Text` property. */ Property getTextProperty() { - result.getDeclaringType() = this - and - result.hasName("Text") - and + result.getDeclaringType() = this and + result.hasName("Text") and result.getType() instanceof StringType } } /** The `System.Web.UI.WebControls.Label` class. */ class SystemWebUIWebControlsLabelClass extends SystemWebUIWebControlsClass { - SystemWebUIWebControlsLabelClass() { - this.hasName("Label") - } + SystemWebUIWebControlsLabelClass() { this.hasName("Label") } /** Gets the `Text` property. */ Property getTextProperty() { - result.getDeclaringType() = this - and - result.hasName("Text") - and + result.getDeclaringType() = this and + result.hasName("Text") and result.getType() instanceof StringType } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/windows/Forms.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/windows/Forms.qll index 78f75e7e3a1..1a15ffe7e6d 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/windows/Forms.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/windows/Forms.qll @@ -1,4 +1,5 @@ /** Provides definitions related to the namespace `System.Windows.Forms`. */ + import csharp private import semmle.code.csharp.frameworks.system.Windows @@ -12,19 +13,13 @@ class SystemWindowsFormsNamespace extends Namespace { /** A class in the `System.Windows.Forms` namespace. */ class SystemWindowsFormsClass extends Class { - SystemWindowsFormsClass() { - this.getNamespace() instanceof SystemWindowsFormsNamespace - } + SystemWindowsFormsClass() { this.getNamespace() instanceof SystemWindowsFormsNamespace } } /** The `System.Windows.Forms.HtmlElement` class. */ class SystemWindowsFormsHtmlElement extends SystemWindowsFormsClass { - SystemWindowsFormsHtmlElement() { - this.hasName("HtmlElement") - } + SystemWindowsFormsHtmlElement() { this.hasName("HtmlElement") } /** Gets the `SetAttribute` method. */ - Method getSetAttributeMethod() { - result = this.getAMethod("SetAttribute") - } + Method getSetAttributeMethod() { result = this.getAMethod("SetAttribute") } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/xml/XPath.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/xml/XPath.qll index 39914dfc77b..143898ce6c3 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/xml/XPath.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/xml/XPath.qll @@ -1,4 +1,5 @@ /** Provides classes related to the namespace `System.Xml.XPath`. */ + import csharp as csharp private import semmle.code.csharp.frameworks.system.Xml as xml @@ -12,16 +13,8 @@ module SystemXmlXPath { } /** A class in the `System.Xml.XPath` namespace. */ - class Class extends csharp::Class { - Class() { - this.getNamespace() instanceof Namespace - } - } + class Class extends csharp::Class { Class() { this.getNamespace() instanceof Namespace } } /** The `System.Xml.XPath.XPathExpression` class. */ - class XPathExpression extends Class { - XPathExpression() { - this.hasName("XPathExpression") - } - } + class XPathExpression extends Class { XPathExpression() { this.hasName("XPathExpression") } } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/test/NUnit.qll b/csharp/ql/src/semmle/code/csharp/frameworks/test/NUnit.qll index b5f30cbbbe1..4bf193f1ecf 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/test/NUnit.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/test/NUnit.qll @@ -1,12 +1,12 @@ /** Provides definitions related to the NUnit test framework. */ + import csharp import semmle.code.csharp.frameworks.Test /** A class that is an NUnit test fixture */ class NUnitFixture extends TestClass { NUnitFixture() { - exists(Attribute fixture | - fixture.getType().hasName("TestFixtureAttribute") | + exists(Attribute fixture | fixture.getType().hasName("TestFixtureAttribute") | fixture.getTarget() = this ) or @@ -19,7 +19,8 @@ class NUnitTestMethod extends TestMethod { NUnitTestMethod() { exists(Attribute test | test.getType().hasName("TestAttribute") or - test.getType().hasName("TestCaseAttribute") | + test.getType().hasName("TestCaseAttribute") + | test.getTarget() = this ) } @@ -35,11 +36,10 @@ class NUnitTestMethod extends TestMethod { exists(Attribute expected | expected.getType().hasName("ExpectedExceptionAttribute") and expected.getTarget() = this - | - if expected.getArgument(0).getType() instanceof StringType then - result.hasQualifiedName(expected.getArgument(0).getValue()) - else - result = expected.getArgument(0).(TypeofExpr).getTypeAccess().getTarget() + | + if expected.getArgument(0).getType() instanceof StringType + then result.hasQualifiedName(expected.getArgument(0).getValue()) + else result = expected.getArgument(0).(TypeofExpr).getTypeAccess().getTarget() ) } } @@ -56,9 +56,7 @@ class NUnitFile extends TestFile { /** An attribute of type `NUnit.Framework.ValueSourceAttribute`. */ class ValueSourceAttribute extends Attribute { - ValueSourceAttribute() { - this.getType().hasQualifiedName("NUnit.Framework.ValueSourceAttribute") - } + ValueSourceAttribute() { this.getType().hasQualifiedName("NUnit.Framework.ValueSourceAttribute") } /** Holds if the first argument is the target type. */ private predicate typeSpecified() { @@ -68,25 +66,16 @@ class ValueSourceAttribute extends Attribute { /** Gets the class where the value source method is declared. */ ValueOrRefType getSourceType() { - if - this.typeSpecified() - then - result = this.getArgument(0).(TypeofExpr).getTypeAccess().getType() - else - exists(Method m | - m.getAParameter() = this.getTarget() | - result = m.getDeclaringType() - ) + if this.typeSpecified() + then result = this.getArgument(0).(TypeofExpr).getTypeAccess().getType() + else exists(Method m | m.getAParameter() = this.getTarget() | result = m.getDeclaringType()) } /** Gets the name of the value source method. */ string getMethodName() { - if - this.typeSpecified() - then - result = this.getArgument(1).getValue() - else - result = this.getArgument(0).getValue() + if this.typeSpecified() + then result = this.getArgument(1).getValue() + else result = this.getArgument(0).getValue() } /** Gets the method acting as the value source. */ @@ -110,22 +99,16 @@ class TestCaseSourceAttribute extends Attribute { /** Gets the class where the value is declared. */ ValueOrRefType getSourceType() { - if - this.typeSpecified() - then - result = this.getArgument(0).(TypeofExpr).getTypeAccess().getType() - else - result = this.getTarget().(Method).getDeclaringType() + if this.typeSpecified() + then result = this.getArgument(0).(TypeofExpr).getTypeAccess().getType() + else result = this.getTarget().(Method).getDeclaringType() } /** Gets the name of the value. */ string getFieldName() { - if - this.typeSpecified() - then - result = this.getArgument(1).getValue() - else - result = this.getArgument(0).getValue() + if this.typeSpecified() + then result = this.getArgument(1).getValue() + else result = this.getArgument(0).getValue() } /** Gets the declaration where the values are declared. */ diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/test/VisualStudio.qll b/csharp/ql/src/semmle/code/csharp/frameworks/test/VisualStudio.qll index 9e73c73f0a0..901bf3a6428 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/test/VisualStudio.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/test/VisualStudio.qll @@ -1,24 +1,20 @@ /** Provides definitions related to the Microsoft Visual Studio Unit Testing Framework. */ + import csharp import semmle.code.csharp.frameworks.Test /** The `Microsoft.VisualStudio.TestTools.UnitTesting` namespace. */ class VSTestNamespace extends Namespace { - VSTestNamespace() { - this.hasQualifiedName("Microsoft.VisualStudio.TestTools.UnitTesting") - } + VSTestNamespace() { this.hasQualifiedName("Microsoft.VisualStudio.TestTools.UnitTesting") } } /** A class that contains test methods. */ class VSTestClass extends TestClass { VSTestClass() { exists(Attribute a, Class c | - c = a.getType() - and - c.getNamespace() instanceof VSTestNamespace - and - c.hasName("TestClassAttribute") - and + c = a.getType() and + c.getNamespace() instanceof VSTestNamespace and + c.hasName("TestClassAttribute") and a.getTarget() = this ) or @@ -30,12 +26,9 @@ class VSTestClass extends TestClass { class VSTestMethod extends TestMethod { VSTestMethod() { exists(Attribute a, Class c | - c = a.getType() - and - c.getNamespace() instanceof VSTestNamespace - and - c.hasName("TestMethodAttribute") - and + c = a.getType() and + c.getNamespace() instanceof VSTestNamespace and + c.hasName("TestMethodAttribute") and a.getTarget() = this ) } @@ -64,45 +57,33 @@ class VSTestAssertClass extends Class { /** Gets an `IsNull(object, ...)` method. */ Method getIsNullMethod() { - result.getDeclaringType() = this - and - result.hasName("IsNull") - and - result.getParameter(0).getType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("IsNull") and + result.getParameter(0).getType() instanceof ObjectType and result.getReturnType() instanceof VoidType } /** Gets an `IsNotNull(object, ...)` method. */ Method getIsNotNullMethod() { - result.getDeclaringType() = this - and - result.hasName("IsNotNull") - and - result.getParameter(0).getType() instanceof ObjectType - and + result.getDeclaringType() = this and + result.hasName("IsNotNull") and + result.getParameter(0).getType() instanceof ObjectType and result.getReturnType() instanceof VoidType } /** Gets an `void IsTrue(bool, ...)` method. */ Method getIsTrueMethod() { - result.getDeclaringType() = this - and - result.hasName("IsTrue") - and - result.getParameter(0).getType() instanceof BoolType - and + result.getDeclaringType() = this and + result.hasName("IsTrue") and + result.getParameter(0).getType() instanceof BoolType and result.getReturnType() instanceof VoidType } /** Gets an `IsFalse(bool, ...)` method. */ Method getIsFalseMethod() { - result.getDeclaringType() = this - and - result.hasName("IsFalse") - and - result.getParameter(0).getType() instanceof BoolType - and + result.getDeclaringType() = this and + result.hasName("IsFalse") and + result.getParameter(0).getType() instanceof BoolType and result.getReturnType() instanceof VoidType } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/test/XUnit.qll b/csharp/ql/src/semmle/code/csharp/frameworks/test/XUnit.qll index fde511a1c6c..590b6365008 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/test/XUnit.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/test/XUnit.qll @@ -1,21 +1,18 @@ /** Provides definitions related to the xUnit.net test framework. */ + import csharp import semmle.code.csharp.frameworks.Test /** The `Xunit` namespace. */ -class XUnitNamespace extends Namespace { - XUnitNamespace() { - this.hasQualifiedName("Xunit") - } -} +class XUnitNamespace extends Namespace { XUnitNamespace() { this.hasQualifiedName("Xunit") } } /** An xUnit test attribute. */ class XUnitTestCaseAttribute extends Attribute { XUnitTestCaseAttribute() { exists(Class c | - c = this.getType() - and - c.getNamespace() instanceof XUnitNamespace | + c = this.getType() and + c.getNamespace() instanceof XUnitNamespace + | c.hasName("FactAttribute") or c.hasName("TheoryAttribute") @@ -25,16 +22,12 @@ class XUnitTestCaseAttribute extends Attribute { /** An xUnit test class. */ class XUnitTestClass extends TestClass { - XUnitTestClass() { - this.getAMethod() instanceof XUnitTestMethod - } + XUnitTestClass() { this.getAMethod() instanceof XUnitTestMethod } } /** An xUnit test method. */ class XUnitTestMethod extends TestMethod { - XUnitTestMethod() { - this = any(XUnitTestCaseAttribute a).getTarget() - } + XUnitTestMethod() { this = any(XUnitTestCaseAttribute a).getTarget() } override predicate expectsException() { none() } } diff --git a/csharp/ql/src/semmle/code/csharp/metrics/Complexity.qll b/csharp/ql/src/semmle/code/csharp/metrics/Complexity.qll index 045c48f9eec..eba300c9072 100644 --- a/csharp/ql/src/semmle/code/csharp/metrics/Complexity.qll +++ b/csharp/ql/src/semmle/code/csharp/metrics/Complexity.qll @@ -3,28 +3,24 @@ import csharp // Branching points in the sense of cyclomatic complexity are binary, // so there should be a branching point for each non-default switch // case (ignoring those that just fall through to the next case). -private -predicate branchingSwitchCase(ConstCase sc) { +private predicate branchingSwitchCase(ConstCase sc) { // in C# the successor of a case is the expression for the case's value not sc = precedingSharedCase(_) and not sc = precedingSharedCase(_) and not defaultFallThrough(sc) } -private -Stmt precedingSharedCase(@case case) { - exists(Stmt parent, int n | case=parent.getChild(n) and result=parent.getChild(n-1)) +private Stmt precedingSharedCase(@case case) { + exists(Stmt parent, int n | case = parent.getChild(n) and result = parent.getChild(n - 1)) } -private -predicate defaultFallThrough(ConstCase sc) { +private predicate defaultFallThrough(ConstCase sc) { precedingSharedCase(sc) instanceof DefaultCase or defaultFallThrough(precedingSharedCase(sc)) } /** A branching statement used for the computation of cyclomatic complexity */ -private -predicate branchingStmt(Stmt stmt) { +private predicate branchingStmt(Stmt stmt) { stmt instanceof IfStmt or stmt instanceof LoopStmt or branchingSwitchCase(stmt) or @@ -32,22 +28,22 @@ predicate branchingStmt(Stmt stmt) { } /** A branching expression used for the computation of cyclomatic complexity */ -private -predicate branchingExpr(Expr expr) { +private predicate branchingExpr(Expr expr) { expr instanceof ConditionalExpr or expr instanceof LogicalAndExpr or expr instanceof LogicalOrExpr or expr instanceof NullCoalescingExpr } -/** the number of branching statements (if, while, do, for, foreach - switch, case, catch) plus the number of branching - expressions (?, &&, ||, ??) plus one. - Callables with a high cyclomatic complexity (> 10) are - hard to test and maintain, given their large number of - possible execution paths. They should be refactored. */ +/** + * the number of branching statements (if, while, do, for, foreach + * switch, case, catch) plus the number of branching + * expressions (?, &&, ||, ??) plus one. + * Callables with a high cyclomatic complexity (> 10) are + * hard to test and maintain, given their large number of + * possible execution paths. They should be refactored. + */ predicate cyclomaticComplexity(/* this */ Callable c, int n) { - n = count(Stmt stmt | branchingStmt(stmt) and stmt.getEnclosingCallable() = c) - + count(Expr expr | branchingExpr(expr) and expr.getEnclosingCallable() = c) - + 1 + n = count(Stmt stmt | branchingStmt(stmt) and stmt.getEnclosingCallable() = c) + + count(Expr expr | branchingExpr(expr) and expr.getEnclosingCallable() = c) + 1 } diff --git a/csharp/ql/src/semmle/code/csharp/metrics/Coupling.qll b/csharp/ql/src/semmle/code/csharp/metrics/Coupling.qll index 82723601202..287e16adcb1 100644 --- a/csharp/ql/src/semmle/code/csharp/metrics/Coupling.qll +++ b/csharp/ql/src/semmle/code/csharp/metrics/Coupling.qll @@ -11,93 +11,111 @@ predicate depends(ValueOrRefType t, ValueOrRefType u) { exists(NestedType nt, Type bt | nt = t and nt.getDeclaringType() = bt and usesType(bt, u)) or // delegate return type - (usesType(t.(DelegateType).getReturnType(), u)) + usesType(t.(DelegateType).getReturnType(), u) or // delegate parameter type - (usesType(t.(DelegateType).getAParameter().getType(), u)) + usesType(t.(DelegateType).getAParameter().getType(), u) or // type of member field exists(Field f | - f.getDeclaringType() = t and - usesType(f.getType(), u)) + f.getDeclaringType() = t and + usesType(f.getType(), u) + ) or // type of member property exists(Property p | - p.getDeclaringType() = t and - usesType(p.getType(), u)) + p.getDeclaringType() = t and + usesType(p.getType(), u) + ) or // type of indexer property exists(Indexer i | - i.getDeclaringType() = t and - usesType(i.getType(), u)) + i.getDeclaringType() = t and + usesType(i.getType(), u) + ) or // type of event property exists(Event e | - e.getDeclaringType() = t and - usesType(e.getType(), u)) + e.getDeclaringType() = t and + usesType(e.getType(), u) + ) or // return type of member method exists(Method m | - not m instanceof ConstructedMethod and - m.getDeclaringType() = t and - usesType(m.getReturnType(), u)) + not m instanceof ConstructedMethod and + m.getDeclaringType() = t and + usesType(m.getReturnType(), u) + ) or // type of member method parameters exists(Callable c | - not c instanceof ConstructedMethod and - c.getDeclaringType() = t and - usesType(c.getAParameter().getType(), u)) + not c instanceof ConstructedMethod and + c.getDeclaringType() = t and + usesType(c.getAParameter().getType(), u) + ) or exists(MethodCall mc, Method m | - mc.getEnclosingCallable().getDeclaringType() = t and - mc.getTarget() = m and - usesType(m.getSourceDeclaration().getDeclaringType(), u)) + mc.getEnclosingCallable().getDeclaringType() = t and + mc.getTarget() = m and + usesType(m.getSourceDeclaration().getDeclaringType(), u) + ) or exists(ObjectCreation oc | - oc.getEnclosingCallable().getDeclaringType() = t and - usesType(oc.getObjectType().getSourceDeclaration(), u)) + oc.getEnclosingCallable().getDeclaringType() = t and + usesType(oc.getObjectType().getSourceDeclaration(), u) + ) or exists(ObjectCreation oc, Field f | - f.getDeclaringType() = t and - f.getInitializer().getAChild*() = oc and - usesType(oc.getObjectType().getSourceDeclaration(), u)) + f.getDeclaringType() = t and + f.getInitializer().getAChild*() = oc and + usesType(oc.getObjectType().getSourceDeclaration(), u) + ) or exists(DelegateCreation oc | - oc.getEnclosingCallable().getDeclaringType() = t and - usesType(oc.getDelegateType().getSourceDeclaration(), u)) + oc.getEnclosingCallable().getDeclaringType() = t and + usesType(oc.getDelegateType().getSourceDeclaration(), u) + ) or exists(DelegateCall dc, DelegateType dt | - dc.getEnclosingCallable().getDeclaringType() = t and - dc.getDelegateExpr().getType() = dt and - usesType(dt.getSourceDeclaration(), u)) + dc.getEnclosingCallable().getDeclaringType() = t and + dc.getDelegateExpr().getType() = dt and + usesType(dt.getSourceDeclaration(), u) + ) or exists(OperatorCall oc, Operator o | - oc.getEnclosingCallable().getDeclaringType() = t and - oc.getTarget() = o and - usesType(o.getSourceDeclaration().getDeclaringType(), u)) + oc.getEnclosingCallable().getDeclaringType() = t and + oc.getTarget() = o and + usesType(o.getSourceDeclaration().getDeclaringType(), u) + ) or exists(MemberAccess ma, Member m | - ma.getEnclosingCallable().getDeclaringType() = t and - ma.getTarget() = m and - usesType(m.getSourceDeclaration().getDeclaringType(), u)) + ma.getEnclosingCallable().getDeclaringType() = t and + ma.getTarget() = m and + usesType(m.getSourceDeclaration().getDeclaringType(), u) + ) or exists(LocalVariableDeclExpr e, LocalVariable v | - e.getEnclosingCallable().getDeclaringType() = t and - e.getVariable() = v and - usesType(v.getType(), u)) + e.getEnclosingCallable().getDeclaringType() = t and + e.getVariable() = v and + usesType(v.getType(), u) + ) or exists(TypeAccess ta | - ta.getEnclosingCallable().getDeclaringType() = t and - usesType(ta.getType(), u)) + ta.getEnclosingCallable().getDeclaringType() = t and + usesType(ta.getType(), u) + ) or exists(CatchClause cc | - cc.getEnclosingCallable().getDeclaringType() = t and - usesType(cc.getCaughtExceptionType(), u)) + cc.getEnclosingCallable().getDeclaringType() = t and + usesType(cc.getCaughtExceptionType(), u) + ) or exists(Attribute a | - t.getAMember() = a.getTarget() or - t.getAnAttribute() = a | - a.getType() = u) + t.getAMember() = a.getTarget() or + t.getAnAttribute() = a + | + a.getType() = u + ) ) } @@ -108,53 +126,59 @@ predicate usesType(Type t, Type u) { usesType(t.(ArrayType).getElementType(), u) } -/** the afferent coupling of a type is the number of types that - * directly depend on it. */ +/** + * the afferent coupling of a type is the number of types that + * directly depend on it. + */ predicate afferentCoupling(/* this */ ValueOrRefType t, int ca) { - ca = count(ValueOrRefType u | depends(u,t)) + ca = count(ValueOrRefType u | depends(u, t)) } -/** The efferent coupling of a type is the number of types that - * it directly depends on. */ +/** + * The efferent coupling of a type is the number of types that + * it directly depends on. + */ predicate efferentCoupling(/* this */ ValueOrRefType t, int ce) { - ce = count(ValueOrRefType u | depends(t,u)) + ce = count(ValueOrRefType u | depends(t, u)) } /* -------- HENDERSON-SELLERS LACK OF COHESION IN METHODS -------- */ - -/* The aim of this metric is to try and determine whether a class - represents one abstraction (good) or multiple abstractions (bad). - If a class represents multiple abstractions, it should be split - up into multiple classes. - - In the Henderson-Sellers method, this is measured as follows: - M = set of methods in class - F = set of fields or properties in class - r(f) = number of methods that access field, property, indexer or event f - = mean of r(f) over f in F - The lack of cohesion is then given by - - - |M| - --------- - 1 - |M| - - We follow the Eclipse metrics plugin by restricting M to methods - that access some field in the same class, and restrict F to - fields that are read by methods in the same class. - - Classes where the value of this metric is higher than 0.9 ought - to be scrutinised for possible splitting. -*/ +/* + * The aim of this metric is to try and determine whether a class + * represents one abstraction (good) or multiple abstractions (bad). + * If a class represents multiple abstractions, it should be split + * up into multiple classes. + * + * In the Henderson-Sellers method, this is measured as follows: + * M = set of methods in class + * F = set of fields or properties in class + * r(f) = number of methods that access field, property, indexer or event f + * = mean of r(f) over f in F + * The lack of cohesion is then given by + * + * - |M| + * --------- + * 1 - |M| + * + * We follow the Eclipse metrics plugin by restricting M to methods + * that access some field in the same class, and restrict F to + * fields that are read by methods in the same class. + * + * Classes where the value of this metric is higher than 0.9 ought + * to be scrutinised for possible splitting. + */ /** whether m accesses field or property f defined in the same type */ predicate accessesLocalFieldOrProperty(Method m, Declaration f) { - (exists(FieldAccess fa | fa.getEnclosingCallable() = m and fa.getTarget() = f) - or - exists(PropertyAccess pa | pa.getEnclosingCallable() = m and pa.getTarget() = f)) and + ( + exists(FieldAccess fa | fa.getEnclosingCallable() = m and fa.getTarget() = f) + or + exists(PropertyAccess pa | pa.getEnclosingCallable() = m and pa.getTarget() = f) + ) and m.getDeclaringType() = f.getDeclaringType() } -/** whether t has a method m that accesses some local field, */ +/** whether t has a method m that accesses some local field, */ predicate hasAccessingMethod(ValueOrRefType t, Method m) { exists(Declaration f | accessesLocalFieldOrProperty(m, f)) and m.getDeclaringType() = t @@ -167,30 +191,26 @@ predicate hasAccessedFieldOrProperty(ValueOrRefType t, Declaration f) { } /** the Henderson-Sellers lack of cohesion metric */ -predicate lackOfCohesionHS(/* this */ ValueOrRefType t, float locm) { +predicate lackOfCohesionHS(/* this */ ValueOrRefType t, float locm) { exists(int m, float r | - // m = number of methods that access some field, property, indexer or event - m = count(Method method | hasAccessingMethod(t, method)) - and - // r = average (over f) of number of methods that access field or property f - r = avg(Field f | - hasAccessedFieldOrProperty(t, f) | - count(Method x | accessesLocalFieldOrProperty(x, f))) - and - // avoid division by zero - m != 1 - and - // compute LCOM - locm = ((r-m)/(1-m)) + // m = number of methods that access some field, property, indexer or event + m = count(Method method | hasAccessingMethod(t, method)) and + // r = average (over f) of number of methods that access field or property f + r = avg(Field f | + hasAccessedFieldOrProperty(t, f) + | + count(Method x | accessesLocalFieldOrProperty(x, f)) + ) and + // avoid division by zero + m != 1 and + // compute LCOM + locm = ((r - m) / (1 - m)) ) } /* -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ */ - /** whether the method m should be excluded from the CK cohesion computation */ -predicate ignoreLackOfCohesionCK(Method m) { - none() -} +predicate ignoreLackOfCohesionCK(Method m) { none() } /** whether m1 and m2 access a common field or property */ predicate shareFieldOrProperty(ValueOrRefType t, Method m1, Method m2) { @@ -232,19 +252,16 @@ predicate methodUsesFieldOrProperty(ValueOrRefType t, Method m, Declaration d) { * High values of `lcom` indicate a lack of cohesion. Specifically, * an `lcom` of greater than 500 indicates a potential problem. */ -predicate lackOfCohesionCK(/* this */ ValueOrRefType t, float locm) { +predicate lackOfCohesionCK(/* this */ ValueOrRefType t, float locm) { exists(int methods, int linked, float n | - methods = count(Method m | t = m.getDeclaringType() and not ignoreLackOfCohesionCK(m)) - and - linked = count(Method m1, Method m2 | shareFieldOrProperty(t, m1, m2)) - and + methods = count(Method m | t = m.getDeclaringType() and not ignoreLackOfCohesionCK(m)) and + linked = count(Method m1, Method m2 | shareFieldOrProperty(t, m1, m2)) and // 1. The number of pairs of methods without a field in common is // the same as the number of pairs of methods minus the number // of pairs of methods *with* a field in common. // 2. The number of pairs of methods, if the number of methods // is C, is (C - 1) * C. - n = ((methods - 1) * methods) / 2.0 - linked - and + n = ((methods - 1) * methods) / 2.0 - linked and ( n < 0 and locm = 0 or diff --git a/csharp/ql/src/semmle/code/csharp/metrics/ExternalDependencies.qll b/csharp/ql/src/semmle/code/csharp/metrics/ExternalDependencies.qll index 3a58fa249b5..32ff0415f4b 100644 --- a/csharp/ql/src/semmle/code/csharp/metrics/ExternalDependencies.qll +++ b/csharp/ql/src/semmle/code/csharp/metrics/ExternalDependencies.qll @@ -5,59 +5,58 @@ * with the assemblies it uses. This creates a metric showing how much each * source file uses external assemblies. */ + import csharp -/** Finds any type use by each source element. Only source declarations - * are considered, not constructed types and methods. */ -private Type getATypeUse(Element elt) -{ - exists(Variable v | elt = v and v.isSourceDeclaration() and result = v.getType()) +/** + * Finds any type use by each source element. Only source declarations + * are considered, not constructed types and methods. + */ +private Type getATypeUse(Element elt) { + exists(Variable v | elt = v and v.isSourceDeclaration() and result = v.getType()) or - exists(ValueOrRefType t | elt = t and t.isSourceDeclaration() and result = t.getABaseType()) + exists(ValueOrRefType t | elt = t and t.isSourceDeclaration() and result = t.getABaseType()) or - exists(Property p | elt = p and p.isSourceDeclaration() and result = p.getType()) + exists(Property p | elt = p and p.isSourceDeclaration() and result = p.getType()) or - exists(Method m | elt = m and m.isSourceDeclaration() and result = m.getReturnType()) + exists(Method m | elt = m and m.isSourceDeclaration() and result = m.getReturnType()) or - result = elt.(Expr).getType() + result = elt.(Expr).getType() or - result = elt.(Attribute).getType() + result = elt.(Attribute).getType() or - result = getATypeUse(elt).(ConstructedType).getATypeArgument() + result = getATypeUse(elt).(ConstructedType).getATypeArgument() or - result = elt.(MethodCall).getTarget().(ConstructedMethod).getATypeArgument() + result = elt.(MethodCall).getTarget().(ConstructedMethod).getATypeArgument() } -private predicate getElementInFile(File file, Element elt, Assembly assembly) -{ - elt.getLocation().getFile() = file - and - assembly = getATypeUse(elt).getLocation() +private predicate getElementInFile(File file, Element elt, Assembly assembly) { + elt.getLocation().getFile() = file and + assembly = getATypeUse(elt).getLocation() } -private predicate excludedAssembly(Assembly assembly) -{ - assembly.getName()="mscorlib" +private predicate excludedAssembly(Assembly assembly) { + assembly.getName() = "mscorlib" or - assembly.getName()="System" + assembly.getName() = "System" or - assembly.getName()="System.Core" + assembly.getName() = "System.Core" or - assembly.getName()="System.Private.CoreLib" + assembly.getName() = "System.Private.CoreLib" } /** * Generate the table of dependencies for the query. */ -predicate externalDependencies(File file, string encodedDependency, int num) -{ +predicate externalDependencies(File file, string encodedDependency, int num) { num = strictcount(Element e | - // Quantify over `assembly` inside the `strictcount`, to avoid multiple entries for - // assemblies with the same name and version - exists(Assembly assembly | - getElementInFile(file, e, assembly) and - not excludedAssembly(assembly) and - encodedDependency = "/" + file.getRelativePath() + "<|>" + assembly.getName() + "<|>" + assembly.getVersion() + // Quantify over `assembly` inside the `strictcount`, to avoid multiple entries for + // assemblies with the same name and version + exists(Assembly assembly | + getElementInFile(file, e, assembly) and + not excludedAssembly(assembly) and + encodedDependency = "/" + file.getRelativePath() + "<|>" + assembly.getName() + "<|>" + + assembly.getVersion() + ) ) - ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/PrivateData.qll b/csharp/ql/src/semmle/code/csharp/security/PrivateData.qll index 616d59f7a91..fddb8b5e6d0 100644 --- a/csharp/ql/src/semmle/code/csharp/security/PrivateData.qll +++ b/csharp/ql/src/semmle/code/csharp/security/PrivateData.qll @@ -8,6 +8,7 @@ * This library is not concerned with credentials. See `SensitiveActions` for expressions related * to credentials. */ + import csharp /** A string for `match` that identifies strings that look like they represent private data. */ @@ -40,26 +41,20 @@ abstract class PrivateDataExpr extends Expr { } /** A method call that might produce private data. */ class PrivateMethodCall extends PrivateDataExpr, MethodCall { PrivateMethodCall() { - exists(string s | this.getTarget().getName().toLowerCase() = s | - s.matches(privateNames()) - ) + exists(string s | this.getTarget().getName().toLowerCase() = s | s.matches(privateNames())) } } /** An indexer access that might produce private data. */ class PrivateIndexerAccess extends PrivateDataExpr, IndexerAccess { PrivateIndexerAccess() { - exists(string s | this.getAnIndex().getValue().toLowerCase() = s | - s.matches(privateNames()) - ) + exists(string s | this.getAnIndex().getValue().toLowerCase() = s | s.matches(privateNames())) } } /** An access to a variable that might contain private data. */ class PrivateVariableAccess extends PrivateDataExpr, VariableAccess { PrivateVariableAccess() { - exists(string s | this.getTarget().getName().toLowerCase() = s | - s.matches(privateNames()) - ) + exists(string s | this.getTarget().getName().toLowerCase() = s | s.matches(privateNames())) } } diff --git a/csharp/ql/src/semmle/code/csharp/security/Sanitizers.qll b/csharp/ql/src/semmle/code/csharp/security/Sanitizers.qll index ee96d36b6ec..9d752191c64 100644 --- a/csharp/ql/src/semmle/code/csharp/security/Sanitizers.qll +++ b/csharp/ql/src/semmle/code/csharp/security/Sanitizers.qll @@ -1,4 +1,5 @@ /** Provides classes for identifying expressions that might be sanitized. */ + import csharp private import semmle.code.csharp.frameworks.system.Net private import semmle.code.csharp.frameworks.system.Web @@ -13,16 +14,15 @@ class HtmlSanitizedExpr extends Expr { m = any(SystemWebHttpUtility h).getAnHtmlEncodeMethod() or m = any(SystemWebHttpServerUtility h).getAnHtmlEncodeMethod() or m = any(SystemWebHttpUtility c).getAnHtmlAttributeEncodeMethod() or - m = any(SystemNetWebUtility h).getAnHtmlEncodeMethod() | - /* - * All four utility classes provide the same pair of Html[Attribute]Encode methods: - * - * - `string Html[Attribute]Encode(string value)` - * - `void Html[Attribute]Encode(string value, TextWriter output)` - * - * In the first form, we treat the call as sanitized, and in the second form - * we treat any subsequent uses of the `output` argument as sanitized. - */ + m = any(SystemNetWebUtility h).getAnHtmlEncodeMethod() + | + // All four utility classes provide the same pair of Html[Attribute]Encode methods: + // + // - `string Html[Attribute]Encode(string value)` + // - `void Html[Attribute]Encode(string value, TextWriter output)` + // + // In the first form, we treat the call as sanitized, and in the second form + // we treat any subsequent uses of the `output` argument as sanitized. m.getNumberOfParameters() = 1 and this = m.getACall() or @@ -43,7 +43,8 @@ class UrlSanitizedExpr extends Expr { exists(Method m | m = any(SystemWebHttpUtility c).getAnUrlEncodeMethod() or m = any(SystemWebHttpServerUtility c).getAnUrlEncodeMethod() or - m = any(SystemNetWebUtility c).getAnUrlEncodeMethod() | + m = any(SystemNetWebUtility c).getAnUrlEncodeMethod() + | this = m.getACall() ) } @@ -53,16 +54,12 @@ class UrlSanitizedExpr extends Expr { * An expression node with a simple type. */ class SimpleTypeSanitizedExpr extends DataFlow::ExprNode { - SimpleTypeSanitizedExpr() { - this.getType() instanceof SimpleType - } + SimpleTypeSanitizedExpr() { this.getType() instanceof SimpleType } } /** * An expression node with type `System.Guid`. */ class GuidSanitizedExpr extends DataFlow::ExprNode { - GuidSanitizedExpr() { - this.getType() instanceof SystemGuid - } + GuidSanitizedExpr() { this.getType() instanceof SystemGuid } } diff --git a/csharp/ql/src/semmle/code/csharp/security/SensitiveActions.qll b/csharp/ql/src/semmle/code/csharp/security/SensitiveActions.qll index 2a2bc362bb2..c82a84dc48d 100644 --- a/csharp/ql/src/semmle/code/csharp/security/SensitiveActions.qll +++ b/csharp/ql/src/semmle/code/csharp/security/SensitiveActions.qll @@ -8,6 +8,7 @@ * In addition, there are methods that ought not to be executed or not in a fashion that the user * can control. This includes authorization methods such as logins, and sending of data, etc. */ + import csharp /** @@ -15,9 +16,7 @@ import csharp */ abstract class AdditionalSensitiveStrings extends string { bindingset[this] - AdditionalSensitiveStrings() { - any() - } + AdditionalSensitiveStrings() { any() } } /** @@ -25,9 +24,7 @@ abstract class AdditionalSensitiveStrings extends string { */ abstract class AdditionalNonSensitiveStrings extends string { bindingset[this] - AdditionalNonSensitiveStrings() { - any() - } + AdditionalNonSensitiveStrings() { any() } } /** A string for `match` that identifies strings that look like they represent secret data. */ @@ -60,18 +57,14 @@ private string nonSuspicious() { /** A variable that may hold a sensitive value. */ class SensitiveVariable extends Variable { SensitiveVariable() { - exists(string s | this.getName().toLowerCase() = s | - s.matches(suspicious()) - ) + exists(string s | this.getName().toLowerCase() = s | s.matches(suspicious())) } } /** A property that may hold a sensitive value. */ class SensitiveProperty extends Property { SensitiveProperty() { - exists(string s | this.getName().toLowerCase() = s | - s.matches(suspicious()) - ) + exists(string s | this.getName().toLowerCase() = s | s.matches(suspicious())) } } @@ -79,15 +72,12 @@ class SensitiveProperty extends Property { class SensitiveLibraryParameter extends Parameter { SensitiveLibraryParameter() { fromLibrary() and - exists(string s | this.getName().toLowerCase() = s | - s.matches(suspicious()) - ) + exists(string s | this.getName().toLowerCase() = s | s.matches(suspicious())) } } /** A `match` pattern for a password. */ -private string password() -{ +private string password() { // A trailing % is too general. E.g. "passwordLength", "passwordComplexity" result = "%password" or result = "%passwd" @@ -95,25 +85,20 @@ private string password() /** A string that matches suspicious but not non-suspicious. */ bindingset[str] -private predicate isSuspicious(string str) -{ - str.toLowerCase().matches(suspicious()) - and +private predicate isSuspicious(string str) { + str.toLowerCase().matches(suspicious()) and not str.toLowerCase().matches(nonSuspicious()) } /** A string that matches a password. */ bindingset[p] -private predicate isPassword(string p) -{ - p.toLowerCase().matches(password()) - and +private predicate isPassword(string p) { + p.toLowerCase().matches(password()) and not p.toLowerCase().matches(nonSuspicious()) } /** Holds if the expression `expr` uses an element with the name `name`. */ -private predicate expressionHasName(Expr expr, string name) -{ +private predicate expressionHasName(Expr expr, string name) { name = expr.(MethodCall).getTarget().getName() or name = expr.(MethodCall).getAnArgument().getValue() @@ -123,9 +108,7 @@ private predicate expressionHasName(Expr expr, string name) /** An expression that may contain a password. */ class PasswordExpr extends Expr { - PasswordExpr() { - exists(string name | expressionHasName(this, name) and isPassword(name)) - } + PasswordExpr() { exists(string name | expressionHasName(this, name) and isPassword(name)) } } /** An expression that might contain sensitive data. */ @@ -134,7 +117,8 @@ abstract class SensitiveExpr extends Expr { } /** A method access that might produce sensitive data. */ class SensitiveMethodAccess extends SensitiveExpr, MethodCall { SensitiveMethodAccess() { - this.getTarget() instanceof SensitiveDataMethod or + this.getTarget() instanceof SensitiveDataMethod + or // This is particularly to pick up methods with an argument like "password", which // may indicate a lookup. isSuspicious(this.getAnArgument().getValue()) @@ -143,25 +127,21 @@ class SensitiveMethodAccess extends SensitiveExpr, MethodCall { /** An access to a variable that might contain sensitive data. */ class SensitiveVariableAccess extends SensitiveExpr, VariableAccess { - SensitiveVariableAccess() { - isSuspicious(this.getTarget().getName()) - } + SensitiveVariableAccess() { isSuspicious(this.getTarget().getName()) } } /** A method that may produce sensitive data. */ -abstract class SensitiveDataMethod extends Method {} +abstract class SensitiveDataMethod extends Method { } /** A method that might return sensitive data, based on the name. */ class CredentialsMethod extends SensitiveDataMethod { CredentialsMethod() { - exists(string s | s = this.getName().toLowerCase() | - s.matches(suspicious()) - ) + exists(string s | s = this.getName().toLowerCase() | s.matches(suspicious())) } } /** A method whose execution may be sensitive. */ -abstract class SensitiveExecutionMethod extends Method {} +abstract class SensitiveExecutionMethod extends Method { } /** A method that may perform authorization. */ class AuthMethod extends SensitiveExecutionMethod { @@ -170,9 +150,8 @@ class AuthMethod extends SensitiveExecutionMethod { ( s.matches("%login%") or s.matches("%auth%") - ) - and not - ( + ) and + not ( s.matches("get%") or s.matches("set%") or s.matches("%loginfo%") @@ -193,7 +172,5 @@ class SendingMethod extends SensitiveExecutionMethod { /** A call to a method that sends data, and so should not be run conditionally on user input. */ class SensitiveExecutionMethodCall extends MethodCall { - SensitiveExecutionMethodCall() { - this.getTarget() instanceof SensitiveExecutionMethod - } + SensitiveExecutionMethodCall() { this.getTarget() instanceof SensitiveExecutionMethod } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll index 434c16d7c09..abb831730ca 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about cleartext storage of sensitive information. */ + import csharp module CleartextStorage { @@ -28,31 +29,18 @@ module CleartextStorage { * A taint-tracking configuration for cleartext storage of sensitive information. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "ClearTextStorage" - } + TaintTrackingConfiguration() { this = "ClearTextStorage" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of sensitive data. */ class SensitiveExprSource extends Source { - SensitiveExprSource() { - this.getExpr() instanceof SensitiveExpr - } + SensitiveExprSource() { this.getExpr() instanceof SensitiveExpr } } /** A call to any method whose name suggests that it encodes or encrypts the parameter. */ @@ -60,7 +48,8 @@ module CleartextStorage { ProtectSanitizer() { exists(Method m, string s | this.getExpr().(MethodCall).getTarget() = m and - m.getName().regexpMatch("(?i).*" + s + ".*") | + m.getName().regexpMatch("(?i).*" + s + ".*") + | s = "protect" or s = "encode" or s = "encrypt" ) } @@ -69,9 +58,5 @@ module CleartextStorage { /** * An external location sink. */ - class ExternalSink extends Sink { - ExternalSink() { - this instanceof ExternalLocationSink - } - } + class ExternalSink extends Sink { ExternalSink() { this instanceof ExternalLocationSink } } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll index 36463cea110..370588726c0 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about user input treated as code vulnerabilities. */ + import csharp module CodeInjection { @@ -27,32 +28,17 @@ module CodeInjection { * A taint-tracking configuration for user input treated as code vulnerabilities. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "CodeInjection" - } + TaintTrackingConfiguration() { this = "CodeInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { } @@ -67,7 +53,8 @@ module CodeInjection { exists(Method m, MethodCall mc | m.getName().matches("CompileAssemblyFromSource%") and m = any(SystemCodeDomCompilerICodeCompilerClass c).getAMethod() and - mc = m.getAnOverrider*().getACall() | + mc = m.getAnOverrider*().getACall() + | this.getExpr() = mc.getArgumentForName("source") or this.getExpr() = mc.getArgumentForName("sources") ) @@ -82,7 +69,8 @@ module CodeInjection { class RoslynCSharpScriptSink extends Sink { RoslynCSharpScriptSink() { exists(Class c | - c.hasQualifiedName("Microsoft.CodeAnalysis.CSharp.Scripting", "CSharpScript") | + c.hasQualifiedName("Microsoft.CodeAnalysis.CSharp.Scripting", "CSharpScript") + | this.getExpr() = c.getAMethod().getACall().getArgumentForName("code") ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll index b645da9ed81..bbc5584fcdd 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about command injection vulnerabilities. */ + import csharp module CommandInjection { @@ -13,7 +14,6 @@ module CommandInjection { */ abstract class Source extends DataFlow::Node { } - /** * A sink for command injection vulnerabilities. */ @@ -28,53 +28,37 @@ module CommandInjection { * A taint-tracking configuration for command injection vulnerabilities. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "CommandInjection" - } + TaintTrackingConfiguration() { this = "CommandInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * A sink in `System.Diagnostic.Process` or its related classes. */ class SystemProcessCommandInjectionSink extends Sink { SystemProcessCommandInjectionSink() { - /* - * Arguments passed directly to the `System.Diagnostics.Process.Start` method. - */ + // Arguments passed directly to the `System.Diagnostics.Process.Start` method exists(SystemDiagnosticsProcessClass processClass | this.getExpr() = processClass.getAStartMethod().getAParameter().getAnAssignedArgument() - ) or - /* - * Values set on a `System.Diagnostics.ProcessStartInfo` class. - */ + ) + or + // Values set on a `System.Diagnostics.ProcessStartInfo` class exists(SystemDiagnosticsProcessStartInfoClass startInfoClass | - this.getExpr() = startInfoClass.getAConstructor().getACall().getAnArgument() or + this.getExpr() = startInfoClass.getAConstructor().getACall().getAnArgument() + or exists(Property p | p = startInfoClass.getArgumentsProperty() or p = startInfoClass.getFileNameProperty() or - p = startInfoClass.getWorkingDirectoryProperty() | + p = startInfoClass.getWorkingDirectoryProperty() + | this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() ) ) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll index bb7e477e788..82542dbc1c6 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about user-controlled bypass of sensitive * methods. */ + import csharp module UserControlledBypassOfSensitiveMethod { @@ -34,43 +35,30 @@ module UserControlledBypassOfSensitiveMethod { * A taint-tracking configuration for user-controlled bypass of sensitive method. */ class Configuration extends TaintTracking::Configuration { - Configuration() { - this = "UserControlledBypassOfSensitiveMethodConfiguration" - } + Configuration() { this = "UserControlledBypassOfSensitiveMethodConfiguration" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** The result of a reverse dns may be user-controlled. */ class ReverseDnsSource extends Source { ReverseDnsSource() { - this.asExpr().(MethodCall).getTarget() = any(SystemNetDnsClass dns).getGetHostByAddressMethod() + this.asExpr().(MethodCall).getTarget() = any(SystemNetDnsClass dns) + .getGetHostByAddressMethod() } } - private predicate conditionControlsCall(SensitiveExecutionMethodCall call, SensitiveExecutionMethod def, Expr e, boolean cond) { - exists(ControlFlow::SuccessorTypes::BooleanSuccessor s | - cond = s.getValue() | + private predicate conditionControlsCall( + SensitiveExecutionMethodCall call, SensitiveExecutionMethod def, Expr e, boolean cond + ) { + exists(ControlFlow::SuccessorTypes::BooleanSuccessor s | cond = s.getValue() | e.controlsElement(call, s) ) and def = call.getTarget() @@ -83,10 +71,8 @@ module UserControlledBypassOfSensitiveMethod { predicate conditionControlsMethod(SensitiveExecutionMethodCall call, Expr e) { exists(SensitiveExecutionMethod def, boolean cond | conditionControlsCall(call, def, e, cond) and - /* - * Exclude this condition if the other branch also contains a call to the same security - * sensitive method. - */ + // Exclude this condition if the other branch also contains a call to the same security + // sensitive method. not conditionControlsCall(_, def, e, cond.booleanNot()) ) } @@ -96,27 +82,25 @@ module UserControlledBypassOfSensitiveMethod { */ class ConditionControllingSensitiveAction extends Sink { private MethodCall sensitiveMethodCall; + ConditionControllingSensitiveAction() { // A condition used to guard a sensitive method call - conditionControlsMethod(sensitiveMethodCall, this.getExpr()) or - /* - * A condition used to guard a sensitive method call, where the condition is `EndsWith`, - * `StartsWith` or `Contains` on a tainted value. Tracking from strings to booleans doesn't - * make sense in all contexts, so this is restricted to this case. - */ + conditionControlsMethod(sensitiveMethodCall, this.getExpr()) + or + // A condition used to guard a sensitive method call, where the condition is `EndsWith`, + // `StartsWith` or `Contains` on a tainted value. Tracking from strings to booleans doesn't + // make sense in all contexts, so this is restricted to this case. exists(MethodCall stringComparisonCall, string methodName | methodName = "EndsWith" or methodName = "StartsWith" or - methodName = "Contains" | + methodName = "Contains" + | stringComparisonCall = any(SystemStringClass s).getAMethod(methodName).getACall() and conditionControlsMethod(sensitiveMethodCall, stringComparisonCall) and stringComparisonCall.getQualifier() = this.getExpr() ) } - override - MethodCall getSensitiveMethodCall() { - result = sensitiveMethodCall - } + override MethodCall getSensitiveMethodCall() { result = sensitiveMethodCall } } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll index e3cb74eb054..b86fa4822ae 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll @@ -3,29 +3,28 @@ import csharp private import semmle.code.csharp.frameworks.system.net.Mail -module Email -{ +module Email { /** A data flow sink for sending email. */ abstract class Sink extends DataFlow::ExprNode { } /** A data flow sink for sending email via `System.Net.Mail.MailMessage`. */ - class MailMessageSink extends Sink - { + class MailMessageSink extends Sink { MailMessageSink() { exists(SystemNetMailMailMessageClass message | // Constructor to the MailMessage - exists(ObjectCreation creation | - creation.getTarget() = message.getAConstructor() | + exists(ObjectCreation creation | creation.getTarget() = message.getAConstructor() | this.getExpr() = creation.getArgumentForName("subject") or - this.getExpr() = creation.getArgumentForName("body")) + this.getExpr() = creation.getArgumentForName("body") + ) or // Assigns to a sensitive property of a MailMessage exists(Property p | p = message.getBodyProperty() or - p = message.getSubjectProperty() | + p = message.getSubjectProperty() + | this.getExpr() = p.getAnAssignedValue() - ) ) + ) } } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll index afcef9ec1e4..45d5794dca6 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about private information flowing unencrypted to an external location. */ + import csharp module ExposureOfPrivateInformation { @@ -27,35 +28,20 @@ module ExposureOfPrivateInformation { * A taint-tracking configuration for private information flowing unencrypted to an external location. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "ExposureOfPrivateInformation" - } + TaintTrackingConfiguration() { this = "ExposureOfPrivateInformation" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } class PrivateDataSource extends Source { - PrivateDataSource() { - this.getExpr() instanceof PrivateDataExpr - } + PrivateDataSource() { this.getExpr() instanceof PrivateDataExpr } } class ExternalLocation extends Sink { - ExternalLocation() { - this instanceof ExternalLocationSink - } + ExternalLocation() { this instanceof ExternalLocationSink } } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll index 0af472dca8e..b37a5104663 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/HardcodedCredentials.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about hard coded credentials. */ + import csharp module HardcodedCredentials { @@ -42,60 +43,45 @@ module HardcodedCredentials { * A taint-tracking configuration for hard coded credentials. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "HardcodedCredentials" - } + TaintTrackingConfiguration() { this = "HardcodedCredentials" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink and - /* - * Ignore values that are ultimately returned by mocks, as they don't represent "real" - * credentials. - */ + // Ignore values that are ultimately returned by mocks, as they don't represent "real" + // credentials. not any(ReturnedByMockObject mock).getAMemberInitializationValue() = sink.asExpr() and not any(ReturnedByMockObject mock).getAnArgument() = sink.asExpr() } - override - predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { super.hasFlow(source, sink) and - /* - * Exclude hard-coded credentials in tests if they only flow to calls to methods with a name - * like "Add*" "Create*" or "Update*". The rationale is that hard-coded credentials within - * tests that are only used for creating or setting values within tests are unlikely to - * represent credentials to some accessible system. - */ + // Exclude hard-coded credentials in tests if they only flow to calls to methods with a name + // like "Add*" "Create*" or "Update*". The rationale is that hard-coded credentials within + // tests that are only used for creating or setting values within tests are unlikely to + // represent credentials to some accessible system. not ( source.asExpr().getFile() instanceof TestFile and exists(MethodCall createOrAddCall, string createOrAddMethodName | createOrAddMethodName.matches("Update%") or createOrAddMethodName.matches("Create%") or - createOrAddMethodName.matches("Add%") | + createOrAddMethodName.matches("Add%") + | createOrAddCall.getTarget().hasName(createOrAddMethodName) and createOrAddCall.getAnArgument() = sink.asExpr() ) ) } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** * A string literal that is not empty. */ class NonEmptyStringLiteral extends Source { - NonEmptyStringLiteral() { - this.getExpr().(StringLiteral).getValue().length() > 1 - } + NonEmptyStringLiteral() { this.getExpr().(StringLiteral).getValue().length() > 1 } } /** @@ -104,9 +90,9 @@ module HardcodedCredentials { class ByteArrayLiteral extends Source { ByteArrayLiteral() { this.getExpr() = any(ArrayCreation ac | - ac.getArrayType().getElementType() instanceof ByteType and - ac.hasInitializer() - ) + ac.getArrayType().getElementType() instanceof ByteType and + ac.hasInitializer() + ) } } @@ -116,16 +102,16 @@ module HardcodedCredentials { class CharArrayLiteral extends Source { CharArrayLiteral() { this.getExpr() = any(ArrayCreation ac | - ac.getArrayType().getElementType() instanceof CharType and - ac.hasInitializer() - ) + ac.getArrayType().getElementType() instanceof CharType and + ac.hasInitializer() + ) } } /** - * Gets a regular expression for matching names of locations (variables, parameters, keys) that - * indicate the value being held is a credential. - */ + * Gets a regular expression for matching names of locations (variables, parameters, keys) that + * indicate the value being held is a credential. + */ private string getACredentialRegex() { result = "(?i).*pass(wd|word|code|phrase)(?!.*question).*" or result = "(?i).*(puid|username|userid).*" or @@ -135,7 +121,9 @@ module HardcodedCredentials { /** * Gets a credential sink, a display name, the operation it exists in, and a description of the sink. */ - private predicate getCredentialSink(Expr sink, string sinkName, Element supplementaryElement, string description) { + private predicate getCredentialSink( + Expr sink, string sinkName, Element supplementaryElement, string description + ) { // An argument to a library call that looks like a credential // "...flows to the [Username] parameter in [call to method CreateUser]" exists(Call call | @@ -144,7 +132,8 @@ module HardcodedCredentials { sink = call.getArgumentForName(sinkName) and sinkName.regexpMatch(getACredentialRegex()) and call.getTarget().fromLibrary() - ) or + ) + or // An argument to a library setter call for a property that looks like a credential // "...flows to the [setter call argument] for the property [UserName]" exists(Property p, Call call | @@ -155,7 +144,8 @@ module HardcodedCredentials { sinkName = "setter call argument" and p.getName().regexpMatch(getACredentialRegex()) and p.fromLibrary() - ) or + ) + or // Sink compared to password variable // "...flows to [] which is compared against [access of UserName]" exists(ComparisonTest ct, VariableAccess credentialAccess, string varName | @@ -176,26 +166,20 @@ module HardcodedCredentials { */ class HardcodedCredentialsSinkExpr extends Sink { private string description; + private Element supplementaryElement; + private string sinkName; + HardcodedCredentialsSinkExpr() { getCredentialSink(this.getExpr(), sinkName, supplementaryElement, description) } - override - string getSinkDescription() { - result = description - } + override string getSinkDescription() { result = description } - override - Element getSupplementaryElement() { - result = supplementaryElement - } + override Element getSupplementaryElement() { result = supplementaryElement } - override - string getSinkName() { - result = sinkName - } + override string getSinkName() { result = sinkName } } /** @@ -203,25 +187,18 @@ module HardcodedCredentials { */ class MembershipUserUserNameSink extends Sink { private Call call; + MembershipUserUserNameSink() { - call.getTarget().getDeclaringType().getABaseType*() instanceof SystemWebSecurityMembershipUserClass and + call.getTarget().getDeclaringType().getABaseType*() instanceof + SystemWebSecurityMembershipUserClass and this.getExpr() = call.getArgumentForName("name") } - override - string getSinkDescription() { - result = "the $@ parameter in $@" - } + override string getSinkDescription() { result = "the $@ parameter in $@" } - override - Element getSupplementaryElement() { - result = call - } + override Element getSupplementaryElement() { result = call } - override - string getSinkName() { - result = "name" - } + override string getSinkName() { result = "name" } } /** @@ -229,25 +206,18 @@ module HardcodedCredentials { */ class X509CertificateDataSink extends Sink { private ObjectCreation x509Creation; + X509CertificateDataSink() { - x509Creation.getTarget().getDeclaringType() instanceof SystemSecurityCryptographyX509CertificatesX509CertificateClass and + x509Creation.getTarget().getDeclaringType() instanceof + SystemSecurityCryptographyX509CertificatesX509CertificateClass and this.getExpr() = x509Creation.getArgumentForName("rawData") } - override - string getSinkDescription() { - result = "the $@ parameter in $@" - } + override string getSinkDescription() { result = "the $@ parameter in $@" } - override - Element getSupplementaryElement() { - result = x509Creation - } + override Element getSupplementaryElement() { result = x509Creation } - override - string getSinkName() { - result = "rawData" - } + override string getSinkName() { result = "rawData" } } /** @@ -255,7 +225,10 @@ module HardcodedCredentials { */ class StringFormatSanitizer extends Sanitizer { StringFormatSanitizer() { - this.getExpr() = any(SystemStringClass s).getFormatMethod().getACall().getArgumentForName("format") + this.getExpr() = any(SystemStringClass s) + .getFormatMethod() + .getACall() + .getArgumentForName("format") } } @@ -265,8 +238,7 @@ module HardcodedCredentials { */ class StringReplaceSanitizer extends Sanitizer { StringReplaceSanitizer() { - exists(SystemStringClass s, Call c | - c = s.getReplaceMethod().getACall() | + exists(SystemStringClass s, Call c | c = s.getReplaceMethod().getACall() | this.getExpr() = c.getArgumentForName("newValue") or this.getExpr() = c.getArgumentForName("newChar") ) @@ -277,8 +249,6 @@ module HardcodedCredentials { * A call to a `ToString()` method, which is considered not to return hard-coded constants. */ class ToStringSanitizer extends Sanitizer { - ToStringSanitizer() { - this.getExpr() = any(Call c | c.getTarget().hasName("ToString")) - } + ToStringSanitizer() { this.getExpr() = any(Call c | c.getTarget().hasName("ToString")) } } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll index 411af0c693c..d4ff5d983b9 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about unvalidated user input that is used to * construct LDAP queries. */ + import csharp module LDAPInjection { @@ -29,32 +30,17 @@ module LDAPInjection { * A taint-tracking configuration for unvalidated user input that is used to construct LDAP queries. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "LDAPInjection" - } + TaintTrackingConfiguration() { this = "LDAPInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * An argument that sets the `Path` property of a `DirectoryEntry` object that is a sink for LDAP @@ -65,12 +51,15 @@ module LDAPInjection { class DirectoryEntryPathSink extends Sink { DirectoryEntryPathSink() { exists(ObjectCreation create | - create.getTarget() = any(SystemDirectoryServicesDirectoryEntryClass d).getAConstructor() | + create.getTarget() = any(SystemDirectoryServicesDirectoryEntryClass d).getAConstructor() + | this.getExpr() = create.getArgumentForName("path") - ) or + ) + or exists(Property path | path = any(SystemDirectoryServicesDirectoryEntryClass d).getAProperty() and - path.hasName("Path") | + path.hasName("Path") + | this.getExpr() = path.getSetter().getACall().getArgument(0) ) } @@ -85,12 +74,15 @@ module LDAPInjection { class DirectorySearcherFilterSink extends Sink { DirectorySearcherFilterSink() { exists(ObjectCreation create | - create.getTarget() = any(SystemDirectoryServicesDirectorySearcherClass d).getAConstructor() | + create.getTarget() = any(SystemDirectoryServicesDirectorySearcherClass d).getAConstructor() + | this.getExpr() = create.getArgumentForName("filter") - ) or - exists(Property filter | + ) + or + exists(Property filter | filter = any(SystemDirectoryServicesDirectorySearcherClass d).getAProperty() and - filter.hasName("Filter")| + filter.hasName("Filter") + | this.getExpr() = filter.getSetter().getACall().getArgument(0) ) } @@ -105,13 +97,16 @@ module LDAPInjection { class SearchRequestFilterSink extends Sink { SearchRequestFilterSink() { exists(ObjectCreation create | - create.getTarget() = any(SystemDirectoryServicesProtocolsSearchRequest d).getAConstructor() | + create.getTarget() = any(SystemDirectoryServicesProtocolsSearchRequest d).getAConstructor() + | this.getExpr() = create.getArgumentForName("ldapFilter") or this.getExpr() = create.getArgumentForName("filter") - ) or + ) + or exists(Property filter | filter = any(SystemDirectoryServicesProtocolsSearchRequest d).getAProperty() and - filter.hasName("Filter")| + filter.hasName("Filter") + | this.getExpr() = filter.getSetter().getACall().getArgument(0) ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll index 12a4fb2cd89..f4667c8486e 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about untrusted user input used in log entries. */ + import csharp module LogForging { @@ -29,47 +30,26 @@ module LogForging { * A taint-tracking configuration for untrusted user input used in log entries. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "LogForging" - } + TaintTrackingConfiguration() { this = "LogForging" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } class HtmlSanitizer extends Sanitizer { - HtmlSanitizer() { - this.asExpr() instanceof HtmlSanitizedExpr - } + HtmlSanitizer() { this.asExpr() instanceof HtmlSanitizedExpr } } /** * A logger type that extends from an ILogger type. */ - private class LoggerType extends RefType { - LoggerType() { - getABaseType*().hasName("ILogger") - } - } + private class LoggerType extends RefType { LoggerType() { getABaseType*().hasName("ILogger") } } /** * An argument to a call to a method on a logger class. @@ -87,9 +67,10 @@ module LogForging { class StringReplaceSanitizer extends Sanitizer { StringReplaceSanitizer() { exists(Method m | - exists(SystemStringClass s | m = s.getReplaceMethod() or m = s.getRemoveMethod()) or + exists(SystemStringClass s | m = s.getReplaceMethod() or m = s.getRemoveMethod()) + or m = any(SystemTextRegularExpressionsRegexClass r).getAReplaceMethod() - | + | this.asExpr() = m.getACall() ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll index eb2be3bca48..06638a0c762 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about untrusted user input processed as XML * without validation against a known schema. */ + import csharp module MissingXMLValidation { @@ -34,32 +35,17 @@ module MissingXMLValidation { * known schema. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "MissingXMLValidation" - } + TaintTrackingConfiguration() { this = "MissingXMLValidation" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * The input argument to a call to `XmlReader.Create` where the input will not be validated against @@ -67,6 +53,7 @@ module MissingXMLValidation { */ class XmlReaderCreateCallSink extends Sink { XmlReaderCreateCall createCall; + XmlReaderCreateCallSink() { // This is the XML that will be processed this.getExpr() = createCall.getArgumentForName("input") @@ -74,27 +61,30 @@ module MissingXMLValidation { override string getReason() { // No settings = no Schema validation - result = "there is no 'XmlReaderSettings' instance specifying schema validation." and not exists(createCall.getSettings()) or - /* - * An XmlReaderSettings instance is passed where: - * - The ValidationType is not set to Schema; or - * - The ValidationType is set to Schema, but: - * - The ProcessInlineSchema option is set (this allows the document to set a schema - * internally); or - * - The ProcessSchemaLocation option is set (this allows the document to reference a - * schema by location that this document will validate against). - */ + result = "there is no 'XmlReaderSettings' instance specifying schema validation." and + not exists(createCall.getSettings()) + or + // An XmlReaderSettings instance is passed where: + // - The ValidationType is not set to Schema; or + // - The ValidationType is set to Schema, but: + // - The ProcessInlineSchema option is set (this allows the document to set a schema + // internally); or + // - The ProcessSchemaLocation option is set (this allows the document to reference a + // schema by location that this document will validate against). result = "the 'XmlReaderSettings' instance does not specify the 'ValidationType' as 'Schema'." and exists(XmlReaderSettingsCreation settingsCreation | - settingsCreation = createCall.getSettings().getASettingsCreation() | + settingsCreation = createCall.getSettings().getASettingsCreation() + | not settingsCreation.getValidationType().hasName("Schema") - ) or + ) + or exists(string badValidationFlag | result = "the 'XmlReaderSettings' instance specifies '" + badValidationFlag + "'." and exists(XmlReaderSettingsCreation settingsCreation | settingsCreation = createCall.getSettings().getASettingsCreation() and settingsCreation.getValidationType().hasName("Schema") and - settingsCreation.getAValidationFlag().hasName(badValidationFlag) | + settingsCreation.getAValidationFlag().hasName(badValidationFlag) + | badValidationFlag = "ProcessInlineSchema" or badValidationFlag = "ProcessSchemaLocation" ) diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll index d50cfb5ad3f..d918b672b98 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about untrusted user input used in dangerous * regular expression operations. */ + import csharp module ReDoS { @@ -28,17 +29,11 @@ module ReDoS { * A taint-tracking configuration for untrusted user input used in dangerous regular expression operations. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "ReDoS" - } + TaintTrackingConfiguration() { this = "ReDoS" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink or // Unfortunately, we cannot add `ExponentialRegexSink` as @@ -49,10 +44,7 @@ module ReDoS { sink.asExpr() = any(RegexOperation ro).getInput() } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { super.hasFlow(source, sink) and @@ -61,11 +53,7 @@ module ReDoS { } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * An expression that represents a regular expression with potential exponential behavior. @@ -74,10 +62,15 @@ module ReDoS { /* * Detect three variants of a common pattern that leads to exponential blow-up. */ + // Example: ([a-z]+.)+ - s.getValue().regexpMatch(".*\\([^()*+\\]]+\\]?(\\*|\\+)\\.?\\)(\\*|\\+).*") or + s.getValue().regexpMatch(".*\\([^()*+\\]]+\\]?(\\*|\\+)\\.?\\)(\\*|\\+).*") + or // Example: (([a-z])?([a-z]+.))+ - s.getValue().regexpMatch(".*\\((\\([^()]+\\)\\?)?\\([^()*+\\]]+\\]?(\\*|\\+)\\.?\\)\\)(\\*|\\+).*") or + s + .getValue() + .regexpMatch(".*\\((\\([^()]+\\)\\?)?\\([^()*+\\]]+\\]?(\\*|\\+)\\.?\\)\\)(\\*|\\+).*") + or // Example: (([a-z])+.)+ s.getValue().regexpMatch(".*\\(\\([^()*+\\]]+\\]?\\)(\\*|\\+)\\.?\\)(\\*|\\+).*") } @@ -87,19 +80,11 @@ module ReDoS { * literals to the pattern argument of a regex. */ class ExponentialRegexDataflow extends DataFlow::Configuration { - ExponentialRegexDataflow() { - this = "ExponentialRegex" - } + ExponentialRegexDataflow() { this = "ExponentialRegex" } - override - predicate isSource(DataFlow::Node s) { - isExponentialRegex(s.asExpr()) - } + override predicate isSource(DataFlow::Node s) { isExponentialRegex(s.asExpr()) } - override - predicate isSink(DataFlow::Node s) { - s.asExpr() = any(RegexOperation c).getPattern() - } + override predicate isSink(DataFlow::Node s) { s.asExpr() = any(RegexOperation c).getPattern() } } /** @@ -110,7 +95,8 @@ module ReDoS { ExponentialRegexSink() { exists(ExponentialRegexDataflow regexDataflow, RegexOperation regexOperation | // Exponential regex flows to the pattern argument - regexDataflow.hasFlow(_, DataFlow::exprNode(regexOperation.getPattern())) | + regexDataflow.hasFlow(_, DataFlow::exprNode(regexOperation.getPattern())) + | // This is used as an input for this pattern this.getExpr() = regexOperation.getInput() and // No timeouts diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll index be731c94913..151dcf406ae 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about untrusted user input used to construct * regular expressions. */ + import csharp module RegexInjection { @@ -28,32 +29,17 @@ module RegexInjection { * A taint-tracking configuration for untrusted user input used to construct regular expressions. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "RegexInjection" - } + TaintTrackingConfiguration() { this = "RegexInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * A `pattern` argument to a construction of a `Regex`. @@ -70,7 +56,8 @@ module RegexInjection { /** A call to `Regex.Escape` that sanitizes the user input for use in a regex. */ class RegexEscapeSanitizer extends Sanitizer { RegexEscapeSanitizer() { - this.getExpr().(MethodCall).getTarget() = any(SystemTextRegularExpressionsRegexClass r).getAMethod("Escape") + this.getExpr().(MethodCall).getTarget() = any(SystemTextRegularExpressionsRegexClass r) + .getAMethod("Escape") } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll index f092ba8fddd..cf54da1fbfc 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about untrusted user input used in resource descriptors. */ + import csharp module ResourceInjection { @@ -27,37 +28,24 @@ module ResourceInjection { * A taint-tracking configuration for untrusted user input used in resource descriptors. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "ResourceInjection" - } + TaintTrackingConfiguration() { this = "ResourceInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** An argument to the `ConnectionString` property on a data connection class. */ class SqlConnectionStringSink extends Sink { SqlConnectionStringSink() { - this.getExpr() = any(SystemDataConnectionClass dataConn).getConnectionStringProperty().getAnAssignedValue() + this.getExpr() = any(SystemDataConnectionClass dataConn) + .getConnectionStringProperty() + .getAnAssignedValue() } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll index 0496d358cbc..ec34cb93c00 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll @@ -1,6 +1,7 @@ /** -* Provides a taint-tracking configuration for reasoning about SQL injection vulnerabilities. -*/ + * Provides a taint-tracking configuration for reasoning about SQL injection vulnerabilities. + */ + import csharp module SqlInjection { @@ -27,35 +28,21 @@ module SqlInjection { * A taint-tracking configuration for SQL injection vulnerabilities. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "SqlInjection" - } + TaintTrackingConfiguration() { this = "SqlInjection" } - override predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** An SQL expression passed to an API call that executes SQL. */ class SqlInjectionExprSink extends Sink { - SqlInjectionExprSink() { - exists(SqlExpr s | this.getExpr() = s.getSql()) - } + SqlInjectionExprSink() { exists(SqlExpr s | this.getExpr() = s.getSql()) } } private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll index 3867efe81fe..bb1832c39ac 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about uncontrolled data in path expression * vulnerabilities. */ + import csharp module TaintedPath { @@ -30,40 +31,24 @@ module TaintedPath { * A taint-tracking configuration for uncontrolled data in path expression vulnerabilities. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "TaintedPath" - } + TaintTrackingConfiguration() { this = "TaintedPath" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * A path argument to a `File` method call. */ class FileCreateSink extends Sink { FileCreateSink() { - exists(Method create | - create = any(SystemIOFileClass f).getAMethod() | + exists(Method create | create = any(SystemIOFileClass f).getAMethod() | this.getExpr() = create.getACall().getArgumentForName("path") ) } @@ -74,8 +59,7 @@ module TaintedPath { */ class DirectorySink extends Sink { DirectorySink() { - exists(Method create | - create = any(SystemIODirectoryClass f).getAMethod() | + exists(Method create | create = any(SystemIODirectoryClass f).getAMethod() | this.getExpr() = create.getACall().getArgumentForName("path") ) } @@ -87,7 +71,8 @@ module TaintedPath { class FileStreamSink extends Sink { FileStreamSink() { exists(ObjectCreation oc | - oc.getTarget().getDeclaringType() = any(SystemIOFileStreamClass f) | + oc.getTarget().getDeclaringType() = any(SystemIOFileStreamClass f) + | this.getExpr() = oc.getArgumentForName("path") ) } @@ -99,7 +84,8 @@ module TaintedPath { class StreamWriterTaintedPathSink extends Sink { StreamWriterTaintedPathSink() { exists(ObjectCreation oc | - oc.getTarget().getDeclaringType() = any(SystemIOStreamWriterClass f) | + oc.getTarget().getDeclaringType() = any(SystemIOStreamWriterClass f) + | this.getExpr() = oc.getArgumentForName("path") ) } @@ -111,26 +97,23 @@ module TaintedPath { private predicate inWeakCheck(Expr e) { // None of these are sufficient to guarantee that a string is safe. exists(MethodCall m, Method def | m.getTarget() = def | + m.getQualifier() = e and ( - m.getQualifier() = e and ( - def.getName() = "StartsWith" or - def.getName() = "EndsWith" - ) - ) or - ( - m.getArgument(0) = e and - ( - def.getName() = "IsNullOrEmpty" or - def.getName() = "IsNullOrWhitespace" or - def = any(SystemIOFileClass f).getAMethod("Exists") or - def = any(SystemIODirectoryClass f).getAMethod("Exists") - ) + def.getName() = "StartsWith" or + def.getName() = "EndsWith" + ) + or + m.getArgument(0) = e and + ( + def.getName() = "IsNullOrEmpty" or + def.getName() = "IsNullOrWhitespace" or + def = any(SystemIOFileClass f).getAMethod("Exists") or + def = any(SystemIODirectoryClass f).getAMethod("Exists") ) - ) or - // Checking against `null` has no bearing on path traversal. - exists(EqualityOperation b | b.getAnOperand() = e | - b.getAnOperand() instanceof NullLiteral ) + or + // Checking against `null` has no bearing on path traversal. + exists(EqualityOperation b | b.getAnOperand() = e | b.getAnOperand() instanceof NullLiteral) } /** @@ -140,9 +123,7 @@ module TaintedPath { */ class PathCheck extends Sanitizer { PathCheck() { - /* - * This expression is structurally replicated in a dominating guard which is not a "weak" check. - */ + // This expression is structurally replicated in a dominating guard which is not a "weak" check. exists(Expr e | this.getExpr().(GuardedExpr).isGuardedBy(_, e, _) and not inWeakCheck(e) @@ -157,7 +138,8 @@ module TaintedPath { RequestMapPathSanitizer() { exists(Method m | m = any(SystemWebHttpRequestClass request).getAMethod() and - m.hasName("MapPath") | + m.hasName("MapPath") + | this.getExpr() = m.getACall() ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll index d1d336f8967..a809ff7bc6c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about unvalidated URL redirect problems. */ + import csharp module UrlRedirect { @@ -30,32 +31,17 @@ module UrlRedirect { * A taint-tracking configuration for reasoning about unvalidated URL redirect vulnerabilities. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "UrlRedirect" - } + TaintTrackingConfiguration() { this = "UrlRedirect" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * A URL argument to a call to `HttpResponse.Redirect()` or `Controller.Redirect()`, that is a @@ -66,11 +52,13 @@ module UrlRedirect { exists(MethodCall mc | mc.getTarget() = any(SystemWebHttpResponseClass response).getRedirectMethod() or mc.getTarget() = any(SystemWebMvcControllerClass response).getARedirectMethod() - | + | // Redirect uses the parameter name url - this.getExpr() = mc.getArgumentForName("url") or + this.getExpr() = mc.getArgumentForName("url") + or // RedirectToAction - this.getExpr() = mc.getArgumentForName("actionName") or + this.getExpr() = mc.getArgumentForName("actionName") + or // RedirectToRoute this.getExpr() = mc.getArgumentForName("routeName") ) @@ -84,7 +72,8 @@ module UrlRedirect { LocationHeaderSink() { exists(MethodCall call | call.getTarget() = any(SystemWebHttpResponseClass r).getAppendHeaderMethod() or - call.getTarget() = any(SystemWebHttpResponseClass r).getAddHeaderMethod() | + call.getTarget() = any(SystemWebHttpResponseClass r).getAddHeaderMethod() + | call.getArgumentForName("name").getValue() = "Location" and this.getExpr() = call.getArgumentForName("value") ) @@ -97,7 +86,8 @@ module UrlRedirect { class HttpServerTransferSink extends Sink { HttpServerTransferSink() { exists(MethodCall call | - call.getTarget() = any(SystemWebHttpServerUtility s).getTransferMethod() | + call.getTarget() = any(SystemWebHttpServerUtility s).getTransferMethod() + | this.getExpr() = call.getArgumentForName("path") ) } @@ -108,8 +98,7 @@ module UrlRedirect { */ class IsLocalUrlSanitizer extends Sanitizer { IsLocalUrlSanitizer() { - exists(MethodCall mc | - mc.getTarget().hasName("IsLocalUrl") | + exists(MethodCall mc | mc.getTarget().hasName("IsLocalUrl") | this.getExpr().(GuardedExpr).isGuardedBy(mc, mc.getArgument(0), true) ) } @@ -142,16 +131,14 @@ module UrlRedirect { /** A call to an URL encoder. */ class UrlEncodeSanitizer extends Sanitizer { - UrlEncodeSanitizer() { - this.getExpr() instanceof UrlSanitizedExpr - } + UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr } } private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { } private class GuidSanitizer extends Sanitizer, GuidSanitizedExpr { } - /** + /** * A URL argument to a call to `HttpResponse.Redirect()` or `Controller.Redirect()`, that is a * sink for URL redirects. */ @@ -160,15 +147,19 @@ module UrlRedirect { exists(MethodCall mc | mc.getTarget() = any(MicrosoftAspNetCoreHttpHttpResponse response).getRedirectMethod() or mc.getTarget() = any(MicrosoftAspNetCoreMvcController response).getARedirectMethod() - | + | // Response.Redirect uses 'location' parameter - this.getExpr() = mc.getArgumentForName("location") or + this.getExpr() = mc.getArgumentForName("location") + or // Redirect uses the parameter name 'url' - this.getExpr() = mc.getArgumentForName("url") or + this.getExpr() = mc.getArgumentForName("url") + or // Controller.RedirectToAction* - this.getExpr() = mc.getArgumentForName("actionName") or + this.getExpr() = mc.getArgumentForName("actionName") + or // Controller.RedirectToRoute* - this.getExpr() = mc.getArgumentForName("routeName") or + this.getExpr() = mc.getArgumentForName("routeName") + or // Controller.RedirectToPage* this.getExpr() = mc.getArgumentForName("pageName") ) @@ -179,36 +170,48 @@ module UrlRedirect { * Anything that is setting "location" header in the response headers. */ class AspNetCoreLocationHeaderSink extends Sink { - AspNetCoreLocationHeaderSink () { + AspNetCoreLocationHeaderSink() { // ResponseHeaders.Location = exists(AssignableDefinition def | - def.getTarget() = any(MicrosoftAspNetCoreHttpResponseHeaders headers).getLocationProperty() | + def.getTarget() = any(MicrosoftAspNetCoreHttpResponseHeaders headers).getLocationProperty() + | this.asExpr() = def.getSource() ) - or // HttpResponse.Headers.Append("location", ) + or + // HttpResponse.Headers.Append("location", ) exists(MethodCall mc, MicrosoftAspNetCoreHttpHeaderDictionaryExtensions ext | mc.getTarget() = ext.getAppendMethod() or mc.getTarget() = ext.getAppendCommaSeparatedValuesMethod() or - mc.getTarget() = ext.getSetCommaSeparatedValuesMethod() | + mc.getTarget() = ext.getSetCommaSeparatedValuesMethod() + | mc.getArgumentForName("key").getValue().toLowerCase() = "location" and - this.getExpr() = mc.getArgument(2)) - or // HttpResponse.Headers.Add("location", ) - exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, PropertyAccess qualifier, MethodCall add | + this.getExpr() = mc.getArgument(2) + ) + or + // HttpResponse.Headers.Add("location", ) + exists( + RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, PropertyAccess qualifier, + MethodCall add + | qualifier.getTarget() = resp.getHeadersProperty() and add.getTarget() = cl.getAMethod("Add") and qualifier = add.getQualifier() and add.getArgument(0).getValue().toLowerCase() = "location" and - this.getExpr() = add.getArgument(1)) - or // HttpResponse.Headers["location"] = - exists(RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, IndexerAccess ci, Call cs, PropertyAccess qualifier | + this.getExpr() = add.getArgument(1) + ) + or + // HttpResponse.Headers["location"] = + exists( + RefType cl, MicrosoftAspNetCoreHttpHttpResponse resp, IndexerAccess ci, Call cs, + PropertyAccess qualifier + | qualifier.getTarget() = resp.getHeadersProperty() and ci.getTarget() = cl.getAnIndexer() and qualifier = ci.getQualifier() and cs.getTarget() = cl.getAnIndexer().getSetter() and cs.getArgument(0).getValue().toLowerCase() = "location" and - this.asExpr() = cs.getArgument(1)) + this.asExpr() = cs.getArgument(1) + ) } } } - - diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll index 3df588f4749..867e92b2272 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about untrusted user input used in XML processing */ + import csharp module XMLEntityInjection { @@ -15,9 +16,7 @@ module XMLEntityInjection { */ abstract class Source extends DataFlow::Node { } - class RemoteSource extends Source { - RemoteSource() { this instanceof RemoteFlowSource } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** * A data flow sink for untrusted user input used in XML processing. @@ -40,18 +39,20 @@ module XMLEntityInjection { // and make the restriction later by overriding // `hasFlow()` below. this.getExpr() = any(MethodCall mc | - mc.getTarget().hasQualifiedName("System.Xml.XmlReader.Create") or - mc.getTarget().hasQualifiedName("System.Xml.XmlDocument.Load") or - mc.getTarget().hasQualifiedName("System.Xml.XmlDocument.LoadXml") - ).getAnArgument() + mc.getTarget().hasQualifiedName("System.Xml.XmlReader.Create") or + mc.getTarget().hasQualifiedName("System.Xml.XmlDocument.Load") or + mc.getTarget().hasQualifiedName("System.Xml.XmlDocument.LoadXml") + ).getAnArgument() or this.getExpr() = any(ObjectCreation oc | - oc.getObjectType().(ValueOrRefType).hasQualifiedName("System.Xml.XmlTextReader") - ).getAnArgument() + oc.getObjectType().(ValueOrRefType).hasQualifiedName("System.Xml.XmlTextReader") + ).getAnArgument() } override string getReason() { - exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(result) | this.getExpr() = r.getAnArgument()) + exists(InsecureXML::InsecureXmlProcessing r | r.isUnsafe(result) | + this.getExpr() = r.getAnArgument() + ) } } @@ -64,24 +65,13 @@ module XMLEntityInjection { * A taint-tracking configuration for untrusted user input used in XML processing. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "XMLInjection" - } + TaintTrackingConfiguration() { this = "XMLInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { super.hasFlow(source, sink) and diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll index 1a23be4cb54..aed85fe4733 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll @@ -1,6 +1,7 @@ /** * Provides a taint-tracking configuration for reasoning about untrusted user input used in XPath expression. */ + import csharp module XPathInjection { @@ -28,44 +29,35 @@ module XPathInjection { * A taint-tracking configuration for untrusted user input used in XPath expression. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "XPathInjection" - } + TaintTrackingConfiguration() { this = "XPathInjection" } - override - predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override - predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } /** The `xpath` argument to an `XPathExpression.Compile(..)` call. */ class XPathExpressionCompileSink extends Sink { XPathExpressionCompileSink() { - this.getExpr() = any(SystemXmlXPath::XPathExpression xpathExpr).getAMethod("Compile").getACall().getArgumentForName("xpath") + this.getExpr() = any(SystemXmlXPath::XPathExpression xpathExpr) + .getAMethod("Compile") + .getACall() + .getArgumentForName("xpath") } } /** The `xpath` argument to an `XmlNode.Select*Node*(..)` call. */ class XmlNodeSink extends Sink { XmlNodeSink() { - this.getExpr() = any(SystemXmlXmlNodeClass xmlNode).getASelectNodeMethod().getACall().getArgumentForName("xpath") + this.getExpr() = any(SystemXmlXmlNodeClass xmlNode) + .getASelectNodeMethod() + .getACall() + .getArgumentForName("xpath") } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index b89dc77b8f8..ae6a9980cf2 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -2,6 +2,7 @@ * Provides a taint-tracking configuration for reasoning about cross-site scripting * (XSS) vulnerabilities. */ + import csharp module XSS { @@ -29,11 +30,12 @@ module XSS { sourceNode = source.asDataFlowNode() and sinkNode = sink.asDataFlowNode() and c.hasFlow(sourceNode, sinkNode) and - message = "is written to HTML or JavaScript" + any(string explanation | - if exists(sinkNode.(Sink).explanation()) - then explanation = ": " + sinkNode.(Sink).explanation() + "." - else explanation = "." - ) + message = "is written to HTML or JavaScript" + + any(string explanation | + if exists(sinkNode.(Sink).explanation()) + then explanation = ": " + sinkNode.(Sink).explanation() + "." + else explanation = "." + ) ) or // flow entirely within ASP inline code @@ -54,6 +56,7 @@ module XSS { class XssNode extends TXssNode { /** Gets a textual representation of this node. */ string toString() { none() } + /** Gets the location of this node. */ Location getLocation() { none() } @@ -74,6 +77,7 @@ module XSS { DataFlow::Node getDataFlowNode() { result = node } override string toString() { result = node.toString() } + override Location getLocation() { result = node.getLocation() } } @@ -87,15 +91,14 @@ module XSS { AspInlineMember getAspInlineMember() { result = member } override string toString() { result = member.toString() } + override Location getLocation() { result = member.getLocation() } } /** * A data flow sink for cross-site scripting (XSS) vulnerabilities. */ - abstract class Sink extends DataFlow::ExprNode { - string explanation() { none() } - } + abstract class Sink extends DataFlow::ExprNode { string explanation() { none() } } /** * A data flow source for cross-site scripting (XSS) vulnerabilities. @@ -111,29 +114,17 @@ module XSS { * A taint-tracking configuration for cross-site scripting (XSS) vulnerabilities. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "XSSDataFlowConfiguration" - } + TaintTrackingConfiguration() { this = "XSSDataFlowConfiguration" } - override predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** A source of remote user input. */ - class RemoteSource extends Source { - RemoteSource() { - this instanceof RemoteFlowSource - } - } + class RemoteSource extends Source { RemoteSource() { this instanceof RemoteFlowSource } } private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { } @@ -141,9 +132,7 @@ module XSS { /** A call to an HTML encoder. */ private class HtmlEncodeSanitizer extends Sanitizer { - HtmlEncodeSanitizer() { - this.getExpr() instanceof HtmlSanitizedExpr - } + HtmlEncodeSanitizer() { this.getExpr() instanceof HtmlSanitizedExpr } } /** @@ -155,9 +144,7 @@ module XSS { * should be safe from XSS. */ private class UrlEncodeSanitizer extends Sanitizer { - UrlEncodeSanitizer() { - this.getExpr() instanceof UrlSanitizedExpr - } + UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr } } /** A sink where the value of the expression may be rendered as HTML. */ @@ -173,7 +160,8 @@ module XSS { m = responseClass.getAWriteMethod() or m = responseClass.getAWriteFileMethod() or m = responseClass.getATransmitFileMethod() or - m = responseClass.getABinaryWriteMethod() | + m = responseClass.getABinaryWriteMethod() + | // Calls to these methods, or overrides of them this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument() ) @@ -187,27 +175,22 @@ module XSS { private class HtmlTextWriterSink extends Sink, HtmlSink { HtmlTextWriterSink() { exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos | + paramPos = 0 and ( - paramPos = 0 and - ( - m = writeClass.getAWriteMethod() or - m = writeClass.getAWriteLineMethod() or - m = writeClass.getAWriteLineNoTabsMethod() or - m = writeClass.getAWriteBeginTagMethod() or - m = writeClass.getAWriteAttributeMethod() - ) - ) or - ( - /* - * The second parameter to the `WriteAttribute` method is the attribute value, which we - * should only consider as tainted if the call does not ask for the attribute value to be - * encoded using the final parameter. - */ - m = writeClass.getAWriteAttributeMethod() and - paramPos = 1 and - not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true + m = writeClass.getAWriteMethod() or + m = writeClass.getAWriteLineMethod() or + m = writeClass.getAWriteLineNoTabsMethod() or + m = writeClass.getAWriteBeginTagMethod() or + m = writeClass.getAWriteAttributeMethod() ) - | + or + // The second parameter to the `WriteAttribute` method is the attribute value, which we + // should only consider as tainted if the call does not ask for the attribute value to be + // encoded using the final parameter. + m = writeClass.getAWriteAttributeMethod() and + paramPos = 1 and + not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true + | c = m.getACall() and this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos)) ) @@ -222,7 +205,8 @@ module XSS { AttributeCollectionSink() { exists(SystemWebUIAttributeCollectionClass ac, Parameter p | p = ac.getAddMethod().getParameter(1) or - p = ac.getItemProperty().getSetter().getParameter(0) | + p = ac.getItemProperty().getSetter().getParameter(0) + | this.getExpr() = p.getAnAssignedArgument() ) } @@ -233,7 +217,10 @@ module XSS { */ private class SetAttributeSink extends Sink, HtmlSink { SetAttributeSink() { - this.getExpr() = any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1) + this.getExpr() = any(SystemWindowsFormsHtmlElement c) + .getSetAttributeMethod() + .getACall() + .getArgument(1) } } @@ -247,12 +234,15 @@ module XSS { p = page.getIDProperty() or p = page.getMetaDescriptionProperty() or p = page.getMetaKeywordsProperty() or - p = page.getTitleProperty() | + p = page.getTitleProperty() + | this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() - ) or + ) + or exists(Method m, SystemWebUIPageClass page | m = page.getRegisterStartupScriptMethod() or - m = page.getRegisterClientScriptBlockMethod() | + m = page.getRegisterClientScriptBlockMethod() + | this.getExpr() = m.getAParameter().getAnAssignedArgument() ) } @@ -267,9 +257,11 @@ module XSS { exists(Method m, SystemWebUIClientScriptManagerClass clientScriptManager, int paramNumber | this.getExpr() = m.getParameter(paramNumber).getAnAssignedArgument() and ( - (paramNumber = 2 and m.getNumberOfParameters() in [3..4]) or - (paramNumber = 3 and m.getNumberOfParameters() = 5) - ) | + paramNumber = 2 and m.getNumberOfParameters() in [3 .. 4] + or + paramNumber = 3 and m.getNumberOfParameters() = 5 + ) + | m = clientScriptManager.getRegisterClientScriptBlockMethod() or m = clientScriptManager.getRegisterStartupScriptMethod() ) @@ -286,7 +278,8 @@ module XSS { declaringType = p.getDeclaringType() and any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and - p.hasName(name) | + p.hasName(name) + | name = "Caption" and (declaringType.hasName("Calendar") or declaringType.hasName("Table")) or @@ -309,7 +302,8 @@ module XSS { exists(Property p, string name | any(SystemWebUINamespace n).getAChildNamespace*() = p.getDeclaringType().getNamespace() and this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and - p.hasName(name) | + p.hasName(name) + | name = "GroupingTest" or name = "GroupName" or name = "Style" or @@ -327,7 +321,7 @@ module XSS { exists(Method m | m.getDeclaringType() instanceof IntegralType or m.getDeclaringType() instanceof FloatingPointType - | + | m.hasName("Parse") and this.getExpr().(Call).getTarget() = m ) @@ -362,7 +356,7 @@ module XSS { exists(ValueOrRefType t | result.getName() = getMemberAccessNameByIndex(code, i) and t.hasMember(result) - | + | // Base case: a member on the code-behind class i = 0 and t = code.getLocation().getFile().(CodeBehindFile).getInheritedType() @@ -381,12 +375,10 @@ module XSS { * `f1.f2...fn[...]()`. The `i`th member is `fi` in all cases. */ private string getMemberAccessNameByIndex(AspInlineCode code, int i) { - /* - * Strip: - * - leading and trailing whitespace, which apparently you're allowed to have - * - trailing parens, so we can recognize nullary method calls - * - trailing square brackets with some contents, to recognize indexing into arrays - */ + // Strip: + // - leading and trailing whitespace, which apparently you're allowed to have + // - trailing parens, so we can recognize nullary method calls + // - trailing square brackets with some contents, to recognize indexing into arrays result = code.getBody().splitAt(".", i).regexpCapture("\\s*(.*?)(\\[.*\\])?(\\(\\))?\\s*", 1) } @@ -398,16 +390,12 @@ module XSS { class AspInlineMember extends AspInlineCode { Member member; - AspInlineMember() { - member = aspxInlineAccess(this) - } + AspInlineMember() { member = aspxInlineAccess(this) } /** Gets the member that this inline code references. */ Member getMember() { result = member } - Type getType() { - result = getMemberType(getMember()) - } + Type getType() { result = getMemberType(getMember()) } } /** Gets a value that is written to the member accessed by the given `AspInlineMember`. */ @@ -432,7 +420,7 @@ module XSS { private string makeUrl(Location l) { exists(string path, int sl, int sc, int el, int ec | l.hasLocationInfo(path, sl, sc, el, ec) and - result = "file://"+path+":"+sl+":"+sc+":"+el+":"+ec + result = "file://" + path + ":" + sl + ":" + sc + ":" + el + ":" + ec ) } @@ -449,12 +437,11 @@ module XSS { /** The ASP inline code element that references a member of the backing class. */ AspInlineMember inline; - AspxCodeSink() { - this.getExpr() = aspWrittenValue(inline) - } + AspxCodeSink() { this.getExpr() = aspWrittenValue(inline) } override string explanation() { - result = "member is [[\"accessed inline\"|\"" +makeUrl(inline.getLocation())+ "\"]] in an ASPX page" + result = "member is [[\"accessed inline\"|\"" + makeUrl(inline.getLocation()) + + "\"]] in an ASPX page" } } @@ -462,7 +449,9 @@ module XSS { private class HttpListenerResponseSink extends Sink { HttpListenerResponseSink() { exists(PropertyAccess responseOutputStream | - responseOutputStream.getProperty() = any(SystemNetHttpListenerResponseClass h).getOutputStreamProperty() | + responseOutputStream.getProperty() = any(SystemNetHttpListenerResponseClass h) + .getOutputStreamProperty() + | DataFlow::localFlow(DataFlow::exprNode(responseOutputStream), this) ) } @@ -478,7 +467,8 @@ module XSS { m = responseClass.getAWriteMethod() or m = responseClass.getAWriteFileMethod() or m = responseClass.getATransmitFileMethod() or - m = responseClass.getABinaryWriteMethod() | + m = responseClass.getABinaryWriteMethod() + | // Calls to these methods, or overrides of them this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument() ) @@ -489,7 +479,9 @@ module XSS { private class ToHtmlString extends Sink, HtmlSink { ToHtmlString() { exists(Method toHtmlString | - toHtmlString = any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and + toHtmlString = any(SystemWebIHtmlString i) + .getToHtmlStringMethod() + .getAnUltimateImplementor() and toHtmlString.canReturn(this.getExpr()) ) } @@ -502,7 +494,8 @@ module XSS { HtmlString() { exists(Class c | c = any(SystemWebMvcMvcHtmlString m) or - c = any(SystemWebHtmlString m) | + c = any(SystemWebHtmlString m) + | this.getExpr() = c.getAConstructor().getACall().getAnArgument() ) } @@ -513,7 +506,9 @@ module XSS { */ private class StringContent extends Sink { StringContent() { - this.getExpr() = any(ObjectCreation oc | oc.getTarget().getDeclaringType().hasQualifiedName("System.Net.Http", "StringContent")).getArgumentForName("content") + this.getExpr() = any(ObjectCreation oc | + oc.getTarget().getDeclaringType().hasQualifiedName("System.Net.Http", "StringContent") + ).getArgumentForName("content") } } @@ -526,23 +521,19 @@ module XSS { this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument() } - override string explanation() { - result = "System.Web.WebPages.WebPage.WriteLiteral() method" - } + override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteral() method" } } /** - * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in - * a `.cshtml` file. - */ + * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in + * a `.cshtml` file. + */ class WebPageWriteLiteralToSink extends Sink, HtmlSink { WebPageWriteLiteralToSink() { this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument() } - override string explanation() { - result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" - } + override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" } } abstract class AspNetCoreSink extends Sink, HtmlSink { } @@ -553,7 +544,10 @@ module XSS { */ class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreSink { MicrosoftAspNetCoreMvcHtmlHelperRawSink() { - this.getExpr() = any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() + this.getExpr() = any(MicrosoftAspNetCoreMvcHtmlHelperClass h) + .getRawMethod() + .getACall() + .getAnArgument() } override string explanation() { @@ -567,7 +561,10 @@ module XSS { */ class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreSink { MicrosoftAspNetRazorPageWriteLiteralSink() { - this.getExpr() = any(MicrosoftAspNetCoreMvcRazorPageBase h).getWriteLiteralMethod().getACall().getAnArgument() + this.getExpr() = any(MicrosoftAspNetCoreMvcRazorPageBase h) + .getWriteLiteralMethod() + .getACall() + .getAnArgument() } override string explanation() { @@ -580,9 +577,10 @@ module XSS { */ class MicrosoftAspNetHtmlStringSink extends AspNetCoreSink { MicrosoftAspNetHtmlStringSink() { - exists (ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | - c.getTarget() = s.getAConstructor() and - this.asExpr() = c.getAnArgument()) + exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | + c.getTarget() = s.getAConstructor() and + this.asExpr() = c.getAnArgument() + ) } } } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ZipSlip.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ZipSlip.qll index 804fd45eaed..e5787a313f9 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ZipSlip.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ZipSlip.qll @@ -1,6 +1,7 @@ /** * Provides a taint tracking configuration for reasoning about unsafe zip extraction. */ + import csharp module ZipSlip { @@ -23,28 +24,19 @@ module ZipSlip { /** A taint tracking configuration for Zip Slip */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "ZipSlipTaintTracking" - } + TaintTrackingConfiguration() { this = "ZipSlipTaintTracking" } - override predicate isSource(DataFlow::Node source) { - source instanceof Source - } + override predicate isSource(DataFlow::Node source) { source instanceof Source } - override predicate isSink(DataFlow::Node sink) { - sink instanceof Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } - override predicate isSanitizer(DataFlow::Node node) { - node instanceof Sanitizer - } + override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } /** An access to the `FullName` property of a `ZipArchiveEntry`. */ class ArchiveFullNameSource extends Source { ArchiveFullNameSource() { - exists(PropertyAccess pa | - this.asExpr() = pa | + exists(PropertyAccess pa | this.asExpr() = pa | pa.getTarget().getDeclaringType().hasQualifiedName("System.IO.Compression.ZipArchiveEntry") and pa.getTarget().getName() = "FullName" ) @@ -67,7 +59,8 @@ module ZipSlip { exists(MethodCall mc | mc.getTarget().hasQualifiedName("System.IO.File", "Open") or mc.getTarget().hasQualifiedName("System.IO.File", "OpenWrite") or - mc.getTarget().hasQualifiedName("System.IO.File", "Create") | + mc.getTarget().hasQualifiedName("System.IO.File", "Create") + | this.asExpr() = mc.getArgumentForName("path") ) } @@ -77,7 +70,8 @@ module ZipSlip { class FileStreamArgSink extends Sink { FileStreamArgSink() { exists(ObjectCreation oc | - oc.getTarget().getDeclaringType().hasQualifiedName("System.IO.FileStream") | + oc.getTarget().getDeclaringType().hasQualifiedName("System.IO.FileStream") + | this.asExpr() = oc.getArgumentForName("path") ) } @@ -91,7 +85,8 @@ module ZipSlip { class FileInfoArgSink extends Sink { FileInfoArgSink() { exists(ObjectCreation oc | - oc.getTarget().getDeclaringType().hasQualifiedName("System.IO.FileInfo") | + oc.getTarget().getDeclaringType().hasQualifiedName("System.IO.FileInfo") + | this.asExpr() = oc.getArgumentForName("fileName") ) } @@ -104,8 +99,7 @@ module ZipSlip { */ class GetFileNameSanitizer extends Sanitizer { GetFileNameSanitizer() { - exists(MethodCall mc | - mc.getTarget().hasQualifiedName("System.IO.Path", "GetFileName") | + exists(MethodCall mc | mc.getTarget().hasQualifiedName("System.IO.Path", "GetFileName") | this.asExpr() = mc ) } @@ -119,8 +113,7 @@ module ZipSlip { */ class SubstringSanitizer extends Sanitizer { SubstringSanitizer() { - exists(MethodCall mc | - mc.getTarget().hasQualifiedName("System.String", "Substring") | + exists(MethodCall mc | mc.getTarget().hasQualifiedName("System.String", "Substring") | this.asExpr() = mc ) } @@ -136,16 +129,16 @@ module ZipSlip { StringCheckSanitizer() { exists(GuardedExpr ge, MethodCall mc, Expr startsWithQualifier | ge = this.asExpr() and - ge.isGuardedBy(mc, startsWithQualifier, true) | + ge.isGuardedBy(mc, startsWithQualifier, true) + | mc.getTarget().hasQualifiedName("System.String", "StartsWith") and mc.getQualifier() = startsWithQualifier and - /* - * A StartsWith check against Path.Combine is not sufficient, because the ".." elements have - * not yet been resolved. - */ + // A StartsWith check against Path.Combine is not sufficient, because the ".." elements have + // not yet been resolved. not exists(MethodCall combineCall | combineCall.getTarget().hasQualifiedName("System.IO.Path", "Combine") and - DataFlow::localFlow(DataFlow::exprNode(combineCall), DataFlow::exprNode(startsWithQualifier)) + DataFlow::localFlow(DataFlow::exprNode(combineCall), + DataFlow::exprNode(startsWithQualifier)) ) ) } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Stored.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Stored.qll index 109d14c0430..4356ddb5d70 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Stored.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Stored.qll @@ -1,14 +1,14 @@ /** * Provides classes representing sources of stored data. */ + import csharp private import semmle.code.csharp.frameworks.system.data.Common private import semmle.code.csharp.frameworks.system.data.Entity private import semmle.code.csharp.frameworks.Sql /** A data flow source of stored user input. */ -abstract class StoredFlowSource extends DataFlow::Node { -} +abstract class StoredFlowSource extends DataFlow::Node { } /** An access of an Entity Framework `Entity` property that may hold stored data. */ class EntityPropertyStoredFlowSource extends StoredFlowSource { @@ -42,7 +42,8 @@ class DbDataReaderStoredFlowSource extends StoredFlowSource { */ class DbDataReaderMethodStoredFlowSource extends StoredFlowSource { DbDataReaderMethodStoredFlowSource() { - this.asExpr().(MethodCall).getTarget().getDeclaringType() = any(SystemDataCommon::DbDataReader dataReader).getASubType*() + this.asExpr().(MethodCall).getTarget().getDeclaringType() = any(SystemDataCommon::DbDataReader dataReader + ).getASubType*() } } @@ -51,6 +52,7 @@ class DbDataReaderMethodStoredFlowSource extends StoredFlowSource { */ class DbDataReaderPropertyStoredFlowSource extends StoredFlowSource { DbDataReaderPropertyStoredFlowSource() { - this.asExpr().(PropertyAccess).getTarget().getDeclaringType() = any(SystemDataCommon::DbDataReader dataReader).getASubType*() + this.asExpr().(PropertyAccess).getTarget().getDeclaringType() = any(SystemDataCommon::DbDataReader dataReader + ).getASubType*() } } diff --git a/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll b/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll index a86ce9b0e6e..1c73df0c82a 100644 --- a/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll +++ b/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll @@ -1,6 +1,7 @@ /** * Provides classes representing external location sinks. */ + import csharp private import semmle.code.csharp.commons.Loggers private import semmle.code.csharp.frameworks.system.Web @@ -18,9 +19,7 @@ abstract class ExternalLocationSink extends DataFlow::ExprNode { } * An argument to a call to a method on a logger class. */ class LogMessageSink extends ExternalLocationSink { - LogMessageSink() { - this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() - } + LogMessageSink() { this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() } } /** @@ -30,7 +29,8 @@ class TraceMessageSink extends ExternalLocationSink { TraceMessageSink() { exists(Class trace, string parameterName | trace.hasQualifiedName("System.Diagnostics", "Trace") or - trace.hasQualifiedName("System.Diagnostics", "TraceSource") | + trace.hasQualifiedName("System.Diagnostics", "TraceSource") + | this.getExpr() = trace.getAMethod().getACall().getArgumentForName(parameterName) and ( parameterName = "format" or @@ -47,13 +47,19 @@ class TraceMessageSink extends ExternalLocationSink { */ class CookieStorageSink extends ExternalLocationSink { CookieStorageSink() { - exists(Expr e | - e = this.getExpr() | - e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value") or + exists(Expr e | e = this.getExpr() | + e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value") + or // Anything set on the Value property - e = any(SystemWebHttpCookie cookie).getProperty("Value").getSetter().getACall().getAnArgument() or + e = any(SystemWebHttpCookie cookie) + .getProperty("Value") + .getSetter() + .getACall() + .getAnArgument() + or // Anything set on any index of the `Values` property - e = any(SystemWebHttpCookie cookie).getValuesProperty().getAnIndexerCall().getArgument(1) or + e = any(SystemWebHttpCookie cookie).getValuesProperty().getAnIndexerCall().getArgument(1) + or // Anything set on any index of the cookie itself e = any(SystemWebHttpCookie cookie).getAnIndexer().getSetter().getACall().getArgument(1) ) diff --git a/csharp/ql/src/semmle/code/csharp/security/xml/InsecureXML.qll b/csharp/ql/src/semmle/code/csharp/security/xml/InsecureXML.qll index 6e99243e623..8ddd396219c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/xml/InsecureXML.qll +++ b/csharp/ql/src/semmle/code/csharp/security/xml/InsecureXML.qll @@ -13,22 +13,23 @@ module InsecureXML { */ bindingset[version] private predicate isNetFrameworkBefore(Type t, string version) { - /* - * For assemblies compiled against framework versions before 4 the TargetFrameworkAttribute - * will not be present. In this case, we can revert back to the assembly version, which may not - * contain full minor version information. - */ + // For assemblies compiled against framework versions before 4 the TargetFrameworkAttribute + // will not be present. In this case, we can revert back to the assembly version, which may not + // contain full minor version information. exists(string assemblyVersion | - assemblyVersion = t.getALocation().(Assembly).getVersion().regexpCapture("([0-9]+\\.[0-9]+).*", 1) | + assemblyVersion = t + .getALocation() + .(Assembly) + .getVersion() + .regexpCapture("([0-9]+\\.[0-9]+).*", 1) + | assemblyVersion.toFloat() < version.toFloat() and // This method is only accurate when we're looking at versions before 4.0. assemblyVersion.toFloat() < 4.0 ) or - /* - * For 4.0 and above the TargetFrameworkAttribute should be present to provide detailed version - * information. - */ + // For 4.0 and above the TargetFrameworkAttribute should be present to provide detailed version + // information. exists(TargetFrameworkAttribute tfa | tfa.hasElement(t) and tfa.isNetFramework() and @@ -78,36 +79,39 @@ module InsecureXML { */ private Expr getAValueForProp(ObjectCreation create, string prop) { // values set in object init - exists(MemberInitializer init | init = create.getInitializer().(ObjectInitializer).getAMemberInitializer() and + exists(MemberInitializer init | + init = create.getInitializer().(ObjectInitializer).getAMemberInitializer() and init.getLValue().(PropertyAccess).getTarget().hasName(prop) and - result = init.getRValue()) or + result = init.getRValue() + ) + or // values set on var that create is assigned to exists(Assignment propAssign | - DataFlow::localFlow(DataFlow::exprNode(create), DataFlow::exprNode(propAssign.getLValue().(PropertyAccess).getQualifier())) and + DataFlow::localFlow(DataFlow::exprNode(create), + DataFlow::exprNode(propAssign.getLValue().(PropertyAccess).getQualifier())) and propAssign.getLValue().(PropertyAccess).getTarget().hasName(prop) and - result = propAssign.getRValue()) + result = propAssign.getRValue() + ) } module XmlSettings { - /** * Holds if the given object creation constructs `XmlReaderSettings` with an insecure resolver. */ predicate insecureResolverSettings(ObjectCreation creation, Expr evidence, string reason) { - creation.getObjectType().getQualifiedName() = "System.Xml.XmlReaderSettings" - and + creation.getObjectType().getQualifiedName() = "System.Xml.XmlReaderSettings" and ( // one unsafe assignment to XmlResolver - exists(Expr xmlResolverVal | - xmlResolverVal = getAValueForProp(creation, "XmlResolver")| + exists(Expr xmlResolverVal | xmlResolverVal = getAValueForProp(creation, "XmlResolver") | not isSafeXmlResolver(xmlResolverVal) and evidence = xmlResolverVal - ) - and reason = "insecure resolver set in settings" + ) and + reason = "insecure resolver set in settings" or // no assignments, and default is insecure before version 4.5 isNetFrameworkBefore(creation.getObjectType(), "4.5") and - not exists(getAValueForProp(creation, "XmlResolver")) - and reason = "default settings resolver is insecure in versions before 4.5" and evidence = creation + not exists(getAValueForProp(creation, "XmlResolver")) and + reason = "default settings resolver is insecure in versions before 4.5" and + evidence = creation ) } @@ -115,97 +119,87 @@ module InsecureXML { * Holds if the given object creation constructs `XmlReaderSettings` with DTD processing enabled. */ predicate dtdEnabledSettings(ObjectCreation creation, Expr evidence, string reason) { - creation.getObjectType().getQualifiedName() = "System.Xml.XmlReaderSettings" - and + creation.getObjectType().getQualifiedName() = "System.Xml.XmlReaderSettings" and ( - ( - exists(Expr dtdVal | - dtdVal = getAValueForProp(creation, "DtdProcessing")| - not isSafeDtdSetting(dtdVal) and evidence = dtdVal - ) - and reason = "DTD processing enabled in settings" - // default is secure in versions >= 4 - ) + exists(Expr dtdVal | dtdVal = getAValueForProp(creation, "DtdProcessing") | + not isSafeDtdSetting(dtdVal) and evidence = dtdVal + ) and + reason = "DTD processing enabled in settings" or + // default is secure in versions >= 4 isNetFrameworkBefore(creation.getObjectType(), "4.0") and ( exists(Expr dtdVal | // different DTD setting before version 4 - dtdVal = getAValueForProp(creation, "ProhibitDtd")| + dtdVal = getAValueForProp(creation, "ProhibitDtd") + | not isSafeDtdSetting(dtdVal) and evidence = dtdVal - ) - and reason = "DTD procesing enabled in settings" + ) and + reason = "DTD procesing enabled in settings" or - not exists(getAValueForProp(creation, "ProhibitDtd")) - and reason = "DTD processing is enabled by default in versions before 4.0" and evidence = creation + not exists(getAValueForProp(creation, "ProhibitDtd")) and + reason = "DTD processing is enabled by default in versions before 4.0" and + evidence = creation ) ) } } module XmlReader { - class InsecureXmlReaderCreate extends InsecureXmlProcessing, MethodCall { - InsecureXmlReaderCreate() { - this.getTarget().hasQualifiedName("System.Xml.XmlReader.Create") - } + InsecureXmlReaderCreate() { this.getTarget().hasQualifiedName("System.Xml.XmlReader.Create") } /** * Gets the `XmlReaderSettings` argument to to this call, if any. */ Expr getSettings() { - result = this.getAnArgument() and result.getType().(RefType).getABaseType*().hasQualifiedName("System.Xml.XmlReaderSettings") + result = this.getAnArgument() and + result.getType().(RefType).getABaseType*().hasQualifiedName("System.Xml.XmlReaderSettings") } override predicate isUnsafe(string reason) { exists(string dtdReason, string resolverReason | - dtdEnabled(dtdReason, _) - and - insecureResolver(resolverReason, _) - and + dtdEnabled(dtdReason, _) and + insecureResolver(resolverReason, _) and reason = dtdReason + ", " + resolverReason ) } private predicate dtdEnabled(string reason, Expr evidence) { - ( - reason="DTD processing is enabled by default in versions < 4.0" and - evidence = this and - not exists(this.getSettings()) and - isNetFrameworkBefore(this.(MethodCall).getTarget().getDeclaringType(), "4.0") - ) + reason = "DTD processing is enabled by default in versions < 4.0" and + evidence = this and + not exists(this.getSettings()) and + isNetFrameworkBefore(this.(MethodCall).getTarget().getDeclaringType(), "4.0") or // bad settings flow here - ( - exists(SettingsDataFlowConfig flow, ObjectCreation settings | - flow.hasFlow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) - and - XmlSettings::dtdEnabledSettings(settings, evidence, reason) - ) + exists(SettingsDataFlowConfig flow, ObjectCreation settings | + flow.hasFlow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) and + XmlSettings::dtdEnabledSettings(settings, evidence, reason) ) } private predicate insecureResolver(string reason, Expr evidence) { // bad settings flow here - ( - exists(SettingsDataFlowConfig flow, ObjectCreation settings | - flow.hasFlow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) - and - XmlSettings::insecureResolverSettings(settings, evidence, reason) - ) + exists(SettingsDataFlowConfig flow, ObjectCreation settings | + flow.hasFlow(DataFlow::exprNode(settings), DataFlow::exprNode(this.getSettings())) and + XmlSettings::insecureResolverSettings(settings, evidence, reason) ) // default is secure } } private class SettingsDataFlowConfig extends DataFlow::Configuration { - SettingsDataFlowConfig() { - this = "SettingsDataFlowConfig" - } + SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" } override predicate isSource(DataFlow::Node source) { // flow from places where we construct an XmlReaderSettings - source.asExpr().(ObjectCreation).getType().(RefType).getABaseType*().hasQualifiedName("System.Xml.XmlReaderSettings") + source + .asExpr() + .(ObjectCreation) + .getType() + .(RefType) + .getABaseType*() + .hasQualifiedName("System.Xml.XmlReaderSettings") } override predicate isSink(DataFlow::Node sink) { @@ -221,56 +215,52 @@ module InsecureXML { } override predicate isUnsafe(string reason) { - ( - not exists(Expr xmlResolverVal | - isSafeXmlResolver(xmlResolverVal) - and xmlResolverVal = getAValueForProp(this, "XmlResolver") - ) - and not exists(Expr dtdVal | - isSafeDtdSetting(dtdVal) and - dtdVal = getAValueForProp(this, "DtdProcessing") - ) - // This was made safe by default in 4.5.2, despite what the documentation says - and isNetFrameworkBefore(this.getObjectType(), "4.5.2") - and reason = "DTD processing is enabled by default, and resolver is insecure by default" - ) + not exists(Expr xmlResolverVal | + isSafeXmlResolver(xmlResolverVal) and + xmlResolverVal = getAValueForProp(this, "XmlResolver") + ) and + not exists(Expr dtdVal | + isSafeDtdSetting(dtdVal) and + dtdVal = getAValueForProp(this, "DtdProcessing") + ) and + // This was made safe by default in 4.5.2, despite what the documentation says + isNetFrameworkBefore(this.getObjectType(), "4.5.2") and + reason = "DTD processing is enabled by default, and resolver is insecure by default" or - ( - exists(Expr xmlResolverVal | - not isSafeXmlResolver(xmlResolverVal) - and xmlResolverVal = getAValueForProp(this, "XmlResolver") - ) - and exists(Expr dtdVal | - not isSafeDtdSetting(dtdVal) and - dtdVal = getAValueForProp(this, "DtdProcessing") - ) - and reason = "DTD processing is enabled with an insecure resolver" - ) + exists(Expr xmlResolverVal | + not isSafeXmlResolver(xmlResolverVal) and + xmlResolverVal = getAValueForProp(this, "XmlResolver") + ) and + exists(Expr dtdVal | + not isSafeDtdSetting(dtdVal) and + dtdVal = getAValueForProp(this, "DtdProcessing") + ) and + reason = "DTD processing is enabled with an insecure resolver" } } } module XmlDocument { - /** * A call to `Load` or `LoadXml` on `XmlDocument`s that doesn't appear to have a safe `XmlResolver` set. */ class InsecureXmlDocument extends InsecureXmlProcessing, MethodCall { InsecureXmlDocument() { - this.getTarget().hasQualifiedName("System.Xml.XmlDocument.Load") - or this.getTarget().hasQualifiedName("System.Xml.XmlDocument.LoadXml") + this.getTarget().hasQualifiedName("System.Xml.XmlDocument.Load") or + this.getTarget().hasQualifiedName("System.Xml.XmlDocument.LoadXml") } - override predicate isUnsafe(string reason) { + override predicate isUnsafe(string reason) { exists(ObjectCreation creation | - DataFlow::localFlow(DataFlow::exprNode(creation), DataFlow::exprNode(this.getQualifier())) | + DataFlow::localFlow(DataFlow::exprNode(creation), DataFlow::exprNode(this.getQualifier())) + | not exists(Expr xmlResolverVal | - isSafeXmlResolver(xmlResolverVal) - and xmlResolverVal = getAValueForProp(creation, "XmlResolver") + isSafeXmlResolver(xmlResolverVal) and + xmlResolverVal = getAValueForProp(creation, "XmlResolver") ) - ) - and isNetFrameworkBefore(this.getQualifier().getType(), "4.6") - and reason = "resolver is insecure by default in versions before 4.6" + ) and + isNetFrameworkBefore(this.getQualifier().getType(), "4.6") and + reason = "resolver is insecure by default in versions before 4.6" } } } diff --git a/csharp/ql/src/semmle/code/dotnet/Callable.qll b/csharp/ql/src/semmle/code/dotnet/Callable.qll index d3eb0397f15..a126aa11d9c 100644 --- a/csharp/ql/src/semmle/code/dotnet/Callable.qll +++ b/csharp/ql/src/semmle/code/dotnet/Callable.qll @@ -13,9 +13,7 @@ class Callable extends Declaration, @dotnet_callable { /** Holds if this callable has a body or an implementation. */ predicate hasBody() { none() } - override Callable getSourceDeclaration() { - result = Declaration.super.getSourceDeclaration() - } + override Callable getSourceDeclaration() { result = Declaration.super.getSourceDeclaration() } /** Gets the number of parameters of this callable. */ int getNumberOfParameters() { result = count(getAParameter()) } @@ -30,33 +28,35 @@ class Callable extends Declaration, @dotnet_callable { predicate canReturn(Expr e) { none() } final override string getLabel() { - result = getReturnTypeLabel() + " " + getDeclaringType().getLabel() + "." + getUndecoratedName() + - getGenericsLabel(this) + getMethodParams() + result = getReturnTypeLabel() + " " + getDeclaringType().getLabel() + "." + getUndecoratedName() + + getGenericsLabel(this) + getMethodParams() } private string getReturnTypeLabel() { - if exists(getReturnType()) - then result = getReturnType().getLabel() - else result = "System.Void" + if exists(getReturnType()) then result = getReturnType().getLabel() else result = "System.Void" } private string getMethodParams() { result = "(" + getMethodParamList() + ")" } - language [monotonicAggregates] + language[monotonicAggregates] private string getMethodParamList() { - result = concat(int p | exists(getParameter(p)) | getParameter(p).getType().getLabel(), "," order by p) + result = concat(int p | + exists(getParameter(p)) + | + getParameter(p).getType().getLabel(), "," + order by + p + ) } - override string getUndecoratedName() { result=getName() } + override string getUndecoratedName() { result = getName() } /** Gets the return type of this callable. */ Type getReturnType() { none() } } /** A constructor. */ -abstract class Constructor extends Callable { -} +abstract class Constructor extends Callable { } /** A destructor/finalizer. */ -abstract class Destructor extends Callable { -} +abstract class Destructor extends Callable { } diff --git a/csharp/ql/src/semmle/code/dotnet/Declaration.qll b/csharp/ql/src/semmle/code/dotnet/Declaration.qll index a8f2145a7b1..f10f7a9d9f3 100644 --- a/csharp/ql/src/semmle/code/dotnet/Declaration.qll +++ b/csharp/ql/src/semmle/code/dotnet/Declaration.qll @@ -7,10 +7,10 @@ import Type /** A declaration. */ class Declaration extends NamedElement, @dotnet_declaration { - override predicate hasQualifiedName(string qualifier, string name) { - qualifier = this.getDeclaringType().getQualifiedName() and - name = this.getName() - } + override predicate hasQualifiedName(string qualifier, string name) { + qualifier = this.getDeclaringType().getQualifiedName() and + name = this.getName() + } /** Gets the name of this declaration, without additional decoration such as `<...>`. */ string getUndecoratedName() { none() } diff --git a/csharp/ql/src/semmle/code/dotnet/Element.qll b/csharp/ql/src/semmle/code/dotnet/Element.qll index 2a45758d414..0ba580b1b56 100644 --- a/csharp/ql/src/semmle/code/dotnet/Element.qll +++ b/csharp/ql/src/semmle/code/dotnet/Element.qll @@ -1,6 +1,7 @@ /** * Provides the .Net `Element` class. */ + private import DotNet import semmle.code.csharp.Location @@ -14,10 +15,10 @@ class Element extends @dotnet_element { /** Gets the location of this element. */ Location getLocation() { none() } - /** - * Gets a location of this element, which can include locations in - * both DLLs and source files. - */ + /** + * Gets a location of this element, which can include locations in + * both DLLs and source files. + */ Location getALocation() { none() } /** Gets the file containing this element. */ @@ -57,12 +58,8 @@ class NamedElement extends Element, @dotnet_named_element { * ``` */ final string getQualifiedName() { - exists(string qualifier, string name | - this.hasQualifiedName(qualifier, name) | - if qualifier = "" then - result = name - else - result = qualifier + "." + name + exists(string qualifier, string name | this.hasQualifiedName(qualifier, name) | + if qualifier = "" then result = name else result = qualifier + "." + name ) } @@ -70,9 +67,7 @@ class NamedElement extends Element, @dotnet_named_element { * Holds if this element has qualified name `qualifiedName`, for example * `System.Console.WriteLine`. */ - final predicate hasQualifiedName(string qualifiedName) { - qualifiedName = this.getQualifiedName() - } + final predicate hasQualifiedName(string qualifiedName) { qualifiedName = this.getQualifiedName() } /** Holds if this element has the qualified name `qualifier`.`name`. */ predicate hasQualifiedName(string qualifier, string name) { @@ -96,10 +91,8 @@ class NamedElement extends Element, @dotnet_named_element { * database. That is, this element corresponds to another element from source. */ predicate compiledFromSource() { - not this.fromSource() - and - exists(NamedElement other | - other != this | + not this.fromSource() and + exists(NamedElement other | other != this | other.getLabel() = this.getLabel() and other.fromSource() ) diff --git a/csharp/ql/src/semmle/code/dotnet/Expr.qll b/csharp/ql/src/semmle/code/dotnet/Expr.qll index 2e1ed3049c4..29a9c6c170d 100644 --- a/csharp/ql/src/semmle/code/dotnet/Expr.qll +++ b/csharp/ql/src/semmle/code/dotnet/Expr.qll @@ -29,7 +29,7 @@ class Call extends Expr, @dotnet_call { /** Gets the target of this call. */ Callable getTarget() { none() } - /* Gets any potential target of this call. */ + /** Gets any potential target of this call. */ Callable getARuntimeTarget() { none() } /** @@ -42,25 +42,20 @@ class Call extends Expr, @dotnet_call { Expr getArgument(int i) { none() } /** Gets an argument to this call. */ - Expr getAnArgument() { result=getArgument(_) } + Expr getAnArgument() { result = getArgument(_) } /** Gets the expression that is supplied for parameter `p`. */ Expr getArgumentForParameter(Parameter p) { none() } } /** A literal expression. */ -class Literal extends Expr, @dotnet_literal { -} +class Literal extends Expr, @dotnet_literal { } /** A string literal expression. */ -class StringLiteral extends Literal, @dotnet_string_literal { -} +class StringLiteral extends Literal, @dotnet_string_literal { } /** An integer literal expression. */ -class IntLiteral extends Literal, @dotnet_int_literal { -} +class IntLiteral extends Literal, @dotnet_int_literal { } /** A `null` literal expression. */ -class NullLiteral extends Literal, @dotnet_null_literal { -} - +class NullLiteral extends Literal, @dotnet_null_literal { } diff --git a/csharp/ql/src/semmle/code/dotnet/Generics.qll b/csharp/ql/src/semmle/code/dotnet/Generics.qll index 8a7ae67042b..fe941d1b613 100644 --- a/csharp/ql/src/semmle/code/dotnet/Generics.qll +++ b/csharp/ql/src/semmle/code/dotnet/Generics.qll @@ -1,4 +1,5 @@ /** Provides classes for generic types and methods. */ + import Declaration /** @@ -13,28 +14,27 @@ abstract class UnboundGeneric extends Generic { abstract TypeParameter getTypeParameter(int i); /** Gets a type parameter, if any. */ - TypeParameter getATypeParameter() { result=getTypeParameter(_) } + TypeParameter getATypeParameter() { result = getTypeParameter(_) } /** * Gets one of the constructed versions of this declaration, * which has been bound to a specific set of types. */ - ConstructedGeneric getAConstructedGeneric() { - result.getUnboundGeneric() = this - } + ConstructedGeneric getAConstructedGeneric() { result.getUnboundGeneric() = this } /** Gets the total number of type parameters. */ - int getNumberOfTypeParameters() { - result = count(int i | exists(this.getTypeParameter(i))) - } + int getNumberOfTypeParameters() { result = count(int i | exists(this.getTypeParameter(i))) } /** Gets the type parameters as a comma-separated string. */ - language [monotonicAggregates] + language[monotonicAggregates] string typeParametersToString() { result = concat(int i | - exists(this.getTypeParameter(i)) | - this.getTypeParameter(i).toStringWithTypes(), ", " order by i asc - ) + exists(this.getTypeParameter(i)) + | + this.getTypeParameter(i).toStringWithTypes(), ", " + order by + i + ) } } @@ -44,23 +44,24 @@ abstract class ConstructedGeneric extends Generic { abstract Type getTypeArgument(int i); /** Gets a type argument, if any. */ - Type getATypeArgument() { result=getTypeArgument(_) } + Type getATypeArgument() { result = getTypeArgument(_) } /** Gets the unbound generic declaration from which this declaration was constructed. */ UnboundGeneric getUnboundGeneric() { none() } /** Gets the total number of type arguments. */ - int getNumberOfTypeArguments() { - result = count(int i | exists(this.getTypeArgument(i))) - } + int getNumberOfTypeArguments() { result = count(int i | exists(this.getTypeArgument(i))) } /** Gets the type arguments as a comma-separated string. */ - language [monotonicAggregates] + language[monotonicAggregates] string typeArgumentsToString() { result = concat(int i | - exists(this.getTypeArgument(i)) | - this.getTypeArgument(i).toStringWithTypes(), ", " order by i asc - ) + exists(this.getTypeArgument(i)) + | + this.getTypeArgument(i).toStringWithTypes(), ", " + order by + i + ) } } @@ -79,5 +80,9 @@ string getGenericsLabel(Declaration d) { language[monotonicAggregates] private string typeArgs(ConstructedGeneric generic) { - result = concat(int p | exists(generic.getTypeArgument(p)) | generic.getTypeArgument(p).getLabel(), ",") + result = concat(int p | + exists(generic.getTypeArgument(p)) + | + generic.getTypeArgument(p).getLabel(), "," + ) } diff --git a/csharp/ql/src/semmle/code/dotnet/Namespace.qll b/csharp/ql/src/semmle/code/dotnet/Namespace.qll index 660f2f8eee9..90e1e124ce6 100644 --- a/csharp/ql/src/semmle/code/dotnet/Namespace.qll +++ b/csharp/ql/src/semmle/code/dotnet/Namespace.qll @@ -1,6 +1,7 @@ /** * Provides the `Namespace` class to represent .Net namespaces. */ + private import Element /** A namespace. */ diff --git a/csharp/ql/src/semmle/code/dotnet/Type.qll b/csharp/ql/src/semmle/code/dotnet/Type.qll index c1a798711be..7bf932c2c57 100644 --- a/csharp/ql/src/semmle/code/dotnet/Type.qll +++ b/csharp/ql/src/semmle/code/dotnet/Type.qll @@ -20,7 +20,6 @@ class Type extends Declaration, @dotnet_type { * A value or reference type. */ class ValueOrRefType extends Type, @dotnet_valueorreftype { - /** Gets the namespace declaring this type, if any. */ Namespace getDeclaringNamespace() { none() } @@ -44,20 +43,15 @@ class ValueOrRefType extends Type, @dotnet_valueorreftype { * A type parameter, for example `T` in `System.Nullable`. */ class TypeParameter extends Type, @dotnet_type_parameter { - /** Gets the generic type or method declaring this type parameter. */ UnboundGeneric getDeclaringGeneric() { this = result.getATypeParameter() } /** Gets the index of this type parameter. For example the index of `U` in `Func` is 1. */ int getIndex() { none() } - final override string getLabel() { - result = "!" + getIndex() - } + final override string getLabel() { result = "!" + getIndex() } - override string getUndecoratedName() { - result = "!" + getIndex() - } + override string getUndecoratedName() { result = "!" + getIndex() } } /** A pointer type. */ diff --git a/csharp/ql/src/semmle/code/dotnet/Utils.qll b/csharp/ql/src/semmle/code/dotnet/Utils.qll index 0f3e4c370f3..42c5b59a5fb 100644 --- a/csharp/ql/src/semmle/code/dotnet/Utils.qll +++ b/csharp/ql/src/semmle/code/dotnet/Utils.qll @@ -7,6 +7,6 @@ import Expr /** A throw element. */ class Throw extends Element, @dotnet_throw { - /** Gets the expression being thrown, if any.*/ + /** Gets the expression being thrown, if any. */ Expr getExpr() { none() } } diff --git a/csharp/ql/src/semmle/code/dotnet/Variable.qll b/csharp/ql/src/semmle/code/dotnet/Variable.qll index 94b67929fde..0ae3706b711 100644 --- a/csharp/ql/src/semmle/code/dotnet/Variable.qll +++ b/csharp/ql/src/semmle/code/dotnet/Variable.qll @@ -8,8 +8,7 @@ class Variable extends Declaration, @dotnet_variable { } /** A .Net field. */ -class Field extends Variable, Member, @dotnet_field { -} +class Field extends Variable, Member, @dotnet_field { } /** A parameter to a .Net callable or property. */ class Parameter extends Variable, @dotnet_parameter { diff --git a/csharp/ql/test/library-tests/types/Types36.ql b/csharp/ql/test/library-tests/types/Types36.ql index 80535ddf54f..cf9c897996b 100644 --- a/csharp/ql/test/library-tests/types/Types36.ql +++ b/csharp/ql/test/library-tests/types/Types36.ql @@ -1,4 +1,3 @@ -/* Ensure that built-in types can be interfaces */ import csharp from Interface i