diff --git a/csharp/ql/src/API Abuse/CallToGCCollect.ql b/csharp/ql/src/API Abuse/CallToGCCollect.ql index 81480090e66..4ffef9caa0a 100644 --- a/csharp/ql/src/API Abuse/CallToGCCollect.ql +++ b/csharp/ql/src/API Abuse/CallToGCCollect.ql @@ -8,12 +8,13 @@ * @tags efficiency * maintainability */ + import csharp from MethodCall c, Method gcCollect where - c.getTarget() = gcCollect - and gcCollect.hasName("Collect") - and gcCollect.hasNoParameters() - and gcCollect.getDeclaringType().hasQualifiedName("System.GC") + c.getTarget() = gcCollect and + gcCollect.hasName("Collect") and + gcCollect.hasNoParameters() and + gcCollect.getDeclaringType().hasQualifiedName("System.GC") select c, "Call to 'GC.Collect()'." diff --git a/csharp/ql/src/API Abuse/CallToObsoleteMethod.ql b/csharp/ql/src/API Abuse/CallToObsoleteMethod.ql index 9aa84ffe373..8967b5abe8c 100644 --- a/csharp/ql/src/API Abuse/CallToObsoleteMethod.ql +++ b/csharp/ql/src/API Abuse/CallToObsoleteMethod.ql @@ -14,13 +14,12 @@ import csharp class ObsoleteAttribute extends Attribute { - ObsoleteAttribute() { - this.getType().hasQualifiedName("System", "ObsoleteAttribute") - } + ObsoleteAttribute() { this.getType().hasQualifiedName("System", "ObsoleteAttribute") } } from MethodCall c, Method m -where m = c.getTarget() -and m.getAnAttribute() instanceof ObsoleteAttribute -and not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute +where + m = c.getTarget() and + m.getAnAttribute() instanceof ObsoleteAttribute and + not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute select c, "Call to obsolete method $@.", m, m.getName() diff --git a/csharp/ql/src/API Abuse/ClassDoesNotImplementEquals.ql b/csharp/ql/src/API Abuse/ClassDoesNotImplementEquals.ql index bedf60c3b2b..c887ea35d4f 100644 --- a/csharp/ql/src/API Abuse/ClassDoesNotImplementEquals.ql +++ b/csharp/ql/src/API Abuse/ClassDoesNotImplementEquals.ql @@ -16,28 +16,30 @@ import semmle.code.csharp.frameworks.System from Class c, Element item, string message, string itemText where - c.isSourceDeclaration() - and not implementsEquals(c) - and not c.isAbstract() - and + c.isSourceDeclaration() and + not implementsEquals(c) and + not c.isAbstract() and ( exists(MethodCall callToEquals | - callToEquals.getTarget() instanceof EqualsMethod - and callToEquals.getQualifier().getType() = c - and message = "but it is called $@" - and item = callToEquals - and itemText = "here" ) + callToEquals.getTarget() instanceof EqualsMethod and + callToEquals.getQualifier().getType() = c and + message = "but it is called $@" and + item = callToEquals and + itemText = "here" + ) or - ( item = c.getAnOperator().(EQOperator) - and message = "but it implements $@" - and itemText = "operator ==" ) + ( + item = c.getAnOperator().(EQOperator) and + message = "but it implements $@" and + itemText = "operator ==" + ) or - exists(IEquatableEqualsMethod eq | item = eq - and eq = c.getAMethod() - and message = "but it implements $@" - and itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals" + exists(IEquatableEqualsMethod eq | + item = eq and + eq = c.getAMethod() and + message = "but it implements $@" and + itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals" ) ) - -select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".", - item, itemText +select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".", item, + itemText diff --git a/csharp/ql/src/API Abuse/ClassImplementsICloneable.ql b/csharp/ql/src/API Abuse/ClassImplementsICloneable.ql index 849fed49841..1bd3eadad6b 100644 --- a/csharp/ql/src/API Abuse/ClassImplementsICloneable.ql +++ b/csharp/ql/src/API Abuse/ClassImplementsICloneable.ql @@ -14,8 +14,8 @@ import csharp from ValueOrRefType c where - c.fromSource() - and c.getABaseInterface+().hasQualifiedName("System", "ICloneable") - and not c.isSealed() - and exists(Method m | m.getDeclaringType() = c and m.hasName("Clone")) + c.fromSource() and + c.getABaseInterface+().hasQualifiedName("System", "ICloneable") and + not c.isSealed() and + exists(Method m | m.getDeclaringType() = c and m.hasName("Clone")) select c, "Class '" + c.getName() + "' implements 'ICloneable'." diff --git a/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql b/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql index 5525d301394..4789179fc6d 100644 --- a/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql +++ b/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql @@ -29,7 +29,8 @@ ExceptionClass getAThrownException(Method m) { or exists(ControlFlowElement cfe | cfe = any(ThrowElement te | result = te.getExpr().getType()) or - cfe = any(MethodCall mc | result = getAThrownException(mc.getARuntimeTarget())) | + cfe = any(MethodCall mc | result = getAThrownException(mc.getARuntimeTarget())) + | cfe.getEnclosingCallable() = m and not isTriedAgainstException(cfe, result) ) @@ -39,7 +40,7 @@ ExceptionClass getAThrownException(Method m) { * Holds if control flow element is tried against throwing an exception of type * `ec`. */ -pragma [noinline] +pragma[noinline] predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) { (cfe instanceof ThrowElement or cfe instanceof MethodCall) and exists(TryStmt ts | @@ -53,22 +54,27 @@ predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) { */ predicate disposeReachableFromDisposableCreation(MethodCall disposeCall, Expr disposableCreation) { // The qualifier of the Dispose call flows from something that introduced a disposable into scope - (disposableCreation instanceof LocalScopeDisposableCreation or disposableCreation instanceof MethodCall) - and DataFlow::localFlowStep+(DataFlow::exprNode(disposableCreation), DataFlow::exprNode(disposeCall.getQualifier())) - and disposeCall.getTarget() instanceof DisposeMethod + ( + disposableCreation instanceof LocalScopeDisposableCreation or + disposableCreation instanceof MethodCall + ) and + DataFlow::localFlowStep+(DataFlow::exprNode(disposableCreation), + DataFlow::exprNode(disposeCall.getQualifier())) and + disposeCall.getTarget() instanceof DisposeMethod } - from MethodCall disposeCall, Expr disposableCreation, MethodCall callThatThrows where - disposeReachableFromDisposableCreation(disposeCall, disposableCreation) + disposeReachableFromDisposableCreation(disposeCall, disposableCreation) and // The dispose call is not, itself, within a dispose method. - and not disposeCall.getEnclosingCallable() instanceof DisposeMethod + not disposeCall.getEnclosingCallable() instanceof DisposeMethod and // Dispose call not within a finally or catch block - and not exists(TryStmt ts | - ts.getACatchClause().getAChild*() = disposeCall or ts.getFinally().getAChild*() = disposeCall) + not exists(TryStmt ts | + ts.getACatchClause().getAChild*() = disposeCall or ts.getFinally().getAChild*() = disposeCall + ) and // At least one method call exists between the allocation and disposal that could throw - and disposableCreation.getAReachableElement() = callThatThrows - and callThatThrows.getAReachableElement() = disposeCall - and exists(getAThrownException(callThatThrows.getARuntimeTarget())) -select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows, callThatThrows.toString() + disposableCreation.getAReachableElement() = callThatThrows and + callThatThrows.getAReachableElement() = disposeCall and + exists(getAThrownException(callThatThrows.getARuntimeTarget())) +select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows, + callThatThrows.toString() diff --git a/csharp/ql/src/API Abuse/FormatMissingArgument.ql b/csharp/ql/src/API Abuse/FormatMissingArgument.ql index c0536beafe5..3e121481d5b 100644 --- a/csharp/ql/src/API Abuse/FormatMissingArgument.ql +++ b/csharp/ql/src/API Abuse/FormatMissingArgument.ql @@ -13,8 +13,9 @@ import csharp import semmle.code.csharp.frameworks.Format from FormatCall format, ValidFormatString src, int used, int supplied -where src = format.getAFormatSource() -and used = src.getAnInsert() -and supplied = format.getSuppliedArguments() -and used >= supplied +where + src = format.getAFormatSource() and + used = src.getAnInsert() and + supplied = format.getSuppliedArguments() and + used >= supplied select format, "Argument '{" + used + "}' has not been supplied to $@ format string.", src, "this" diff --git a/csharp/ql/src/API Abuse/FormatUnusedArgument.ql b/csharp/ql/src/API Abuse/FormatUnusedArgument.ql index c3ab968110d..fa069b4a150 100644 --- a/csharp/ql/src/API Abuse/FormatUnusedArgument.ql +++ b/csharp/ql/src/API Abuse/FormatUnusedArgument.ql @@ -13,6 +13,8 @@ import csharp import semmle.code.csharp.frameworks.Format from FormatCall format, int unused, ValidFormatString src -where src = format.getAFormatSource() -and unused = format.getAnUnusedArgument(src) -select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused), "this supplied value" +where + src = format.getAFormatSource() and + unused = format.getAnUnusedArgument(src) +select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused), + "this supplied value" diff --git a/csharp/ql/src/API Abuse/InconsistentEqualsGetHashCode.ql b/csharp/ql/src/API Abuse/InconsistentEqualsGetHashCode.ql index f52815051d3..d91db675557 100644 --- a/csharp/ql/src/API Abuse/InconsistentEqualsGetHashCode.ql +++ b/csharp/ql/src/API Abuse/InconsistentEqualsGetHashCode.ql @@ -10,22 +10,25 @@ * maintainability * external/cwe/cwe-581 */ + import csharp import semmle.code.csharp.frameworks.System from Class c, Method present, string missing -where c.isSourceDeclaration() and +where + c.isSourceDeclaration() and ( ( - present = (EqualsMethod)c.getAMethod() and + present = c.getAMethod().(EqualsMethod) and not c.getAMethod() instanceof GetHashCodeMethod and missing = "GetHashCode()" - ) or + ) + or ( - present = (GetHashCodeMethod)c.getAMethod() and + present = c.getAMethod().(GetHashCodeMethod) and not implementsEquals(c) and missing = "Equals(object)" ) ) -select c, "Class '" + c.getName() + "' overrides $@, but not " + missing + ".", - present, present.getName() +select c, "Class '" + c.getName() + "' overrides $@, but not " + missing + ".", present, + present.getName() diff --git a/csharp/ql/src/API Abuse/IncorrectCompareToSignature.ql b/csharp/ql/src/API Abuse/IncorrectCompareToSignature.ql index 2ae84161d3d..c660356d7a0 100644 --- a/csharp/ql/src/API Abuse/IncorrectCompareToSignature.ql +++ b/csharp/ql/src/API Abuse/IncorrectCompareToSignature.ql @@ -13,8 +13,7 @@ import csharp import semmle.code.csharp.frameworks.System predicate implementsIComparable(ValueOrRefType t, Type paramType) { - exists(ConstructedType ct | - t.getABaseType+() = ct | + exists(ConstructedType ct | t.getABaseType+() = ct | ct = any(SystemIComparableTInterface i).getAConstructedGeneric() and paramType = ct.getATypeArgument() ) @@ -28,20 +27,21 @@ predicate implementsIComparable(ValueOrRefType t, Type paramType) { } predicate compareToMethod(Method m, Type paramType) { - m.hasName("CompareTo") - and m.fromSource() - and m.isPublic() - and m.getReturnType() instanceof IntType - and m.getNumberOfParameters() = 1 - and paramType = m.getAParameter().getType() + m.hasName("CompareTo") and + m.fromSource() and + m.isPublic() and + m.getReturnType() instanceof IntType and + m.getNumberOfParameters() = 1 and + paramType = m.getAParameter().getType() } from Method m, RefType declaringType, Type actualParamType -where m.isSourceDeclaration() - and declaringType = m.getDeclaringType() - and compareToMethod(m, actualParamType) - and not implementsIComparable(declaringType, actualParamType) -select m, "The parameter of this 'CompareTo' method is of type $@, but $@ does not implement 'IComparable<$@>'.", - actualParamType, actualParamType.getName(), - declaringType, declaringType.getName(), +where + m.isSourceDeclaration() and + declaringType = m.getDeclaringType() and + compareToMethod(m, actualParamType) and + not implementsIComparable(declaringType, actualParamType) +select m, + "The parameter of this 'CompareTo' method is of type $@, but $@ does not implement 'IComparable<$@>'.", + actualParamType, actualParamType.getName(), declaringType, declaringType.getName(), actualParamType, actualParamType.getName() diff --git a/csharp/ql/src/API Abuse/IncorrectEqualsSignature.ql b/csharp/ql/src/API Abuse/IncorrectEqualsSignature.ql index b04c9f29c44..7103cae4906 100644 --- a/csharp/ql/src/API Abuse/IncorrectEqualsSignature.ql +++ b/csharp/ql/src/API Abuse/IncorrectEqualsSignature.ql @@ -14,21 +14,22 @@ import semmle.code.csharp.frameworks.System class EqualsOtherMethod extends Method { EqualsOtherMethod() { - this.hasName("Equals") - and this.getNumberOfParameters() = 1 - and this.getReturnType() instanceof BoolType - and this.getDeclaringType() instanceof Class - and not this instanceof EqualsMethod - and not this instanceof IEquatableEqualsMethod + this.hasName("Equals") and + this.getNumberOfParameters() = 1 and + this.getReturnType() instanceof BoolType and + this.getDeclaringType() instanceof Class and + not this instanceof EqualsMethod and + not this instanceof IEquatableEqualsMethod } - Type getType() { - result = this.getParameter(0).getType() - } + Type getType() { result = this.getParameter(0).getType() } } from EqualsOtherMethod equalsOther -where equalsOther.isSourceDeclaration() - and not implementsEquals(equalsOther.getDeclaringType()) -select equalsOther, "The $@ of this 'Equals(" + equalsOther.getType().getName() + ")' method does not override 'Equals(object)'.", - equalsOther.getDeclaringType(), "declaring type" +where + equalsOther.isSourceDeclaration() and + not implementsEquals(equalsOther.getDeclaringType()) +select equalsOther, + "The $@ of this 'Equals(" + equalsOther.getType().getName() + + ")' method does not override 'Equals(object)'.", equalsOther.getDeclaringType(), + "declaring type" diff --git a/csharp/ql/src/API Abuse/MissingDisposeCall.ql b/csharp/ql/src/API Abuse/MissingDisposeCall.ql index 110c07ed11a..d84c167a241 100644 --- a/csharp/ql/src/API Abuse/MissingDisposeCall.ql +++ b/csharp/ql/src/API Abuse/MissingDisposeCall.ql @@ -17,15 +17,16 @@ import Dispose import semmle.code.csharp.frameworks.System from DisposableType t, DisposableField f, Method dispose -where f.getDeclaringType() = t - and not f.isStatic() - and t.isSourceDeclaration() - and dispose = getInvokedDisposeMethod(t) - and dispose.getDeclaringType() = t - and not exists(MethodCall mc | - mc.getTarget() instanceof DisposeMethod - and mc.getQualifier() = f.getAnAccess() - and mc.getEnclosingCallable() = dispose +where + f.getDeclaringType() = t and + not f.isStatic() and + t.isSourceDeclaration() and + dispose = getInvokedDisposeMethod(t) and + dispose.getDeclaringType() = t and + not exists(MethodCall mc | + mc.getTarget() instanceof DisposeMethod and + mc.getQualifier() = f.getAnAccess() and + mc.getEnclosingCallable() = dispose ) -select dispose, "This 'Dispose()' method does not call 'Dispose()' on `IDisposable` field $@.", - f, f.getName() +select dispose, "This 'Dispose()' method does not call 'Dispose()' on `IDisposable` field $@.", f, + f.getName() diff --git a/csharp/ql/src/API Abuse/MissingDisposeMethod.ql b/csharp/ql/src/API Abuse/MissingDisposeMethod.ql index e759db266c5..f7fd07bdc71 100644 --- a/csharp/ql/src/API Abuse/MissingDisposeMethod.ql +++ b/csharp/ql/src/API Abuse/MissingDisposeMethod.ql @@ -17,10 +17,10 @@ import Dispose import semmle.code.csharp.frameworks.System from DisposableType t, DisposableField f -where f.getDeclaringType() = t - and t.isSourceDeclaration() - and not f.isStatic() - and not implementsDispose(t) - and not isAutoDisposedWebControl(f) -select t, "This type does not override 'Dispose()' but has disposable field $@.", - f, f.getName() +where + f.getDeclaringType() = t and + t.isSourceDeclaration() and + not f.isStatic() and + not implementsDispose(t) and + not isAutoDisposedWebControl(f) +select t, "This type does not override 'Dispose()' but has disposable field $@.", f, f.getName() diff --git a/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql b/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql index 5c32576c881..315413948c0 100644 --- a/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql +++ b/csharp/ql/src/API Abuse/NoDisposeCallOnLocalIDisposable.ql @@ -22,55 +22,57 @@ import semmle.code.csharp.commons.Disposal /** Holds if expression `e` escapes the local method scope. */ predicate escapes(Expr e) { // Things that return escape - exists(Callable c | c.canReturn(e) or c.canYieldReturn(e)) or + exists(Callable c | c.canReturn(e) or c.canYieldReturn(e)) + or // Things that are assigned to fields, properties, or indexers escape the scope exists(AssignableDefinition def, Assignable a | def.getSource() = e and - a = def.getTarget() | + a = def.getTarget() + | a instanceof Field or a instanceof Property or a instanceof Indexer - ) or - // Things that are added to a collection of some kind are likely to escape the scope - exists(MethodCall mc | - mc.getTarget().hasName("Add") | - mc.getAnArgument() = e ) + or + // Things that are added to a collection of some kind are likely to escape the scope + exists(MethodCall mc | mc.getTarget().hasName("Add") | mc.getAnArgument() = e) } /** Holds if the `disposable` is a whitelisted result. */ predicate isWhitelisted(LocalScopeDisposableCreation disposable) { exists(MethodCall mc | // Close can often be used instead of Dispose - mc.getTarget().hasName("Close") or + mc.getTarget().hasName("Close") + or // Used as an alias for Dispose mc.getTarget().hasName("Clear") - | + | mc.getQualifier() = disposable.getADisposeTarget() - ) or + ) + or // WebControls are usually disposed automatically disposable.getType() instanceof WebControl } from LocalScopeDisposableCreation disposable - // The disposable is local scope - the lifetime is the execution of this method -where not escapes(disposable.getADisposeTarget()) +// The disposable is local scope - the lifetime is the execution of this method +where + not escapes(disposable.getADisposeTarget()) and // Only care about library types - user types often have spurious IDisposable declarations - and disposable.getType().fromLibrary() + disposable.getType().fromLibrary() and // Disposables constructed in the initializer of a `using` are safe - and not exists(UsingStmt us | us.getAnExpr() = disposable.getADisposeTarget()) + not exists(UsingStmt us | us.getAnExpr() = disposable.getADisposeTarget()) and // Foreach calls Dispose - and not exists(ForeachStmt fs | fs.getIterableExpr() = disposable.getADisposeTarget()) + not exists(ForeachStmt fs | fs.getIterableExpr() = disposable.getADisposeTarget()) and // As are disposables on which the Dispose method is called explicitly - and not exists(MethodCall mc | - mc.getTarget() instanceof DisposeMethod - and mc.getQualifier() = disposable.getADisposeTarget() - ) + not exists(MethodCall mc | + mc.getTarget() instanceof DisposeMethod and + mc.getQualifier() = disposable.getADisposeTarget() + ) and // Ignore whitelisted results - and not isWhitelisted(disposable) + not isWhitelisted(disposable) and // Not passed to a disposing method - and not exists(Call c, Parameter p | - disposable.getADisposeTarget() = c.getArgumentForParameter(p) | + not exists(Call c, Parameter p | disposable.getADisposeTarget() = c.getArgumentForParameter(p) | mayBeDisposed(p) ) select disposable, "Disposable '" + disposable.getType() + "' is created here but is not disposed." diff --git a/csharp/ql/src/API Abuse/NonOverridingMethod.ql b/csharp/ql/src/API Abuse/NonOverridingMethod.ql index 5dde64fe865..a51416f67c8 100644 --- a/csharp/ql/src/API Abuse/NonOverridingMethod.ql +++ b/csharp/ql/src/API Abuse/NonOverridingMethod.ql @@ -21,23 +21,24 @@ private predicate potentialOverride(Method vm, Method m) { * but does not do so. */ predicate nonOverridingMethod(Method m, Method vm) { - vm.isVirtual() - and not vm.isOverride() - and not vm.overrides() - and potentialOverride(vm, m) - and not m.overrides() - and not m.isOverride() - and not m.isNew() - and m=m.getSourceDeclaration() - and m.getNumberOfParameters() = vm.getNumberOfParameters() - and forall(int i, Parameter p1, Parameter p2 | - p1=m.getParameter(i) and p2=vm.getParameter(i) | - p1.getType() = p2.getType()) - and m.getName().toLowerCase() = vm.getName().toLowerCase() + vm.isVirtual() and + not vm.isOverride() and + not vm.overrides() and + potentialOverride(vm, m) and + not m.overrides() and + not m.isOverride() and + not m.isNew() and + m = m.getSourceDeclaration() and + m.getNumberOfParameters() = vm.getNumberOfParameters() and + forall(int i, Parameter p1, Parameter p2 | p1 = m.getParameter(i) and p2 = vm.getParameter(i) | + p1.getType() = p2.getType() + ) and + m.getName().toLowerCase() = vm.getName().toLowerCase() } from Method m, Method vm -where m.fromSource() - and nonOverridingMethod(m, vm) +where + m.fromSource() and + nonOverridingMethod(m, vm) select m, "Method '" + m.getName() + "' looks like it should override $@ but does not do so.", vm.getSourceDeclaration(), vm.getQualifiedName() diff --git a/csharp/ql/src/API Abuse/NullArgumentToEquals.ql b/csharp/ql/src/API Abuse/NullArgumentToEquals.ql index 5aeec03037a..a50f64d5696 100644 --- a/csharp/ql/src/API Abuse/NullArgumentToEquals.ql +++ b/csharp/ql/src/API Abuse/NullArgumentToEquals.ql @@ -14,7 +14,8 @@ import csharp import semmle.code.csharp.frameworks.System from MethodCall c, EqualsMethod equals -where c.getTarget().getSourceDeclaration() = equals - and c.getArgument(0) instanceof NullLiteral - and not c.getQualifier().getType() instanceof NullableType +where + c.getTarget().getSourceDeclaration() = equals and + c.getArgument(0) instanceof NullLiteral and + not c.getQualifier().getType() instanceof NullableType select c, "Equality test with 'null' will never be true, but may throw a 'NullReferenceException'." diff --git a/csharp/ql/src/API Abuse/UncheckedReturnValue.ql b/csharp/ql/src/API Abuse/UncheckedReturnValue.ql index bc6def7bd79..fbd066e4d01 100644 --- a/csharp/ql/src/API Abuse/UncheckedReturnValue.ql +++ b/csharp/ql/src/API Abuse/UncheckedReturnValue.ql @@ -12,19 +12,18 @@ * statistical * non-attributable */ + import csharp import semmle.code.csharp.frameworks.system.IO import semmle.code.csharp.Chaining /** Holds if `m` is a method whose return value should always be checked. */ predicate important(Method m) { - exists(Method read | - read = any(SystemIOStreamClass c).getReadMethod() | + exists(Method read | read = any(SystemIOStreamClass c).getReadMethod() | m = read.getAnOverrider*() ) or - exists(Method readByte | - readByte = any(SystemIOStreamClass c).getReadByteMethod() | + exists(Method readByte | readByte = any(SystemIOStreamClass c).getReadByteMethod() | m = readByte.getAnOverrider*() ) // add more ... @@ -49,14 +48,14 @@ predicate dubious(Method m, int percentage) { exists(int used, int total, Method target | target = m.getSourceDeclaration() and used = count(MethodCall mc | - mc.getTarget().getSourceDeclaration() = target and - not mc instanceof DiscardedMethodCall and - (methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType()) - ) and + mc.getTarget().getSourceDeclaration() = target and + not mc instanceof DiscardedMethodCall and + (methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType()) + ) and total = count(MethodCall mc | - mc.getTarget().getSourceDeclaration() = target and - (methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType()) - ) and + mc.getTarget().getSourceDeclaration() = target and + (methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType()) + ) and used != total and percentage = used * 100 / total and percentage >= 90 and @@ -66,9 +65,9 @@ predicate dubious(Method m, int percentage) { int chainedUses(Method m) { result = count(MethodCall mc, MethodCall qual | - m = mc.getTarget() and - hasQualifierAndTarget(mc, qual, qual.getTarget()) - ) + m = mc.getTarget() and + hasQualifierAndTarget(mc, qual, qual.getTarget()) + ) } predicate hasQualifierAndTarget(MethodCall mc, Expr qualifier, Method m) { @@ -78,10 +77,11 @@ predicate hasQualifierAndTarget(MethodCall mc, Expr qualifier, Method m) { /** Holds if `m` is a white-listed method where checking the return value is not required. */ predicate whitelist(Method m) { - m.hasName("TryGetValue") or - m.hasName("TryParse") or - exists(Namespace n | - n = m.getDeclaringType().getNamespace().getParentNamespace*() | + m.hasName("TryGetValue") + or + m.hasName("TryParse") + or + exists(Namespace n | n = m.getDeclaringType().getNamespace().getParentNamespace*() | n.getName().regexpMatch("(Fluent)?NHibernate") or n.getName() = "Moq" ) @@ -89,9 +89,7 @@ predicate whitelist(Method m) { } class DiscardedMethodCall extends MethodCall { - DiscardedMethodCall() { - this.getParent() instanceof ExprStmt - } + DiscardedMethodCall() { this.getParent() instanceof ExprStmt } string query() { exists(Method m | @@ -99,11 +97,11 @@ class DiscardedMethodCall extends MethodCall { not whitelist(m) and // Do not alert on "void wrapper methods", i.e., methods that are inserted // to deliberately ignore the returned value - not getEnclosingCallable().getStatementBody().getNumberOfStmts() = 1 | + not getEnclosingCallable().getStatementBody().getNumberOfStmts() = 1 + | (important(m) and result = "should always be checked") or - exists(int percentage | - dubious(m, percentage) | + exists(int percentage | dubious(m, percentage) | result = percentage.toString() + "% of calls to this method have their result used" ) ) diff --git a/csharp/ql/src/ASP/NonInternationalizedText.ql b/csharp/ql/src/ASP/NonInternationalizedText.ql index 12654788c86..aa23a9e0ea1 100644 --- a/csharp/ql/src/ASP/NonInternationalizedText.ql +++ b/csharp/ql/src/ASP/NonInternationalizedText.ql @@ -12,6 +12,5 @@ import semmle.code.asp.AspNet from AspText text -where - exists(text.getBody().regexpFind("\\w{3,}", _, _)) +where exists(text.getBody().regexpFind("\\w{3,}", _, _)) select text, "This text has not been internationalized." diff --git a/csharp/ql/src/ASP/SplitControlStructure.ql b/csharp/ql/src/ASP/SplitControlStructure.ql index 5a1f46c053d..de7d44ccc1e 100644 --- a/csharp/ql/src/ASP/SplitControlStructure.ql +++ b/csharp/ql/src/ASP/SplitControlStructure.ql @@ -12,6 +12,5 @@ import semmle.code.asp.AspNet from AspCode code -where - exists(code.getBody().regexpFind("(Then|\\{)\\s*$",_,_)) +where exists(code.getBody().regexpFind("(Then|\\{)\\s*$", _, _)) select code, "Split control structure." diff --git a/csharp/ql/src/AlertSuppression.ql b/csharp/ql/src/AlertSuppression.ql index 74b1cd27575..34bf3ab92a2 100644 --- a/csharp/ql/src/AlertSuppression.ql +++ b/csharp/ql/src/AlertSuppression.ql @@ -14,8 +14,7 @@ class SuppressionComment extends SinglelineComment { string annotation; SuppressionComment() { - exists(string text | - text = this.getText() | + exists(string text | text = this.getText() | // match `lgtm[...]` anywhere in the comment annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _) or @@ -25,57 +24,49 @@ class SuppressionComment extends SinglelineComment { } /** Gets the suppression annotation in this comment. */ - string getAnnotation() { - result = annotation - } + string getAnnotation() { result = annotation } /** - * Holds if this comment applies to the range from column `startcolumn` of line `startline` - * to column `endcolumn` of line `endline` in file `filepath`. - */ + * Holds if this comment applies to the range from column `startcolumn` of line `startline` + * to column `endcolumn` of line `endline` in file `filepath`. + */ predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) { this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and startcolumn = 1 } /** Gets the scope of this suppression. */ - SuppressionScope getScope() { - this = result.getSuppressionComment() - } + SuppressionScope getScope() { this = result.getSuppressionComment() } } /** * The scope of an alert suppression comment. */ class SuppressionScope extends @commentline { - SuppressionScope() { - this instanceof SuppressionComment - } + SuppressionScope() { this instanceof SuppressionComment } /** Gets a suppression comment with this scope. */ - SuppressionComment getSuppressionComment() { - result = this - } + SuppressionComment getSuppressionComment() { result = this } /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [LGTM locations](https://lgtm.com/help/ql/locations). - */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [LGTM locations](https://lgtm.com/help/ql/locations). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn) } /** Gets a textual representation of this element. */ - string toString() { - result = "suppression range" - } + string toString() { result = "suppression range" } } from SuppressionComment c -select c, // suppression comment - c.getText(), // text of suppression comment (excluding delimiters) - c.getAnnotation(), // text of suppression annotation - c.getScope() // scope of suppression +select c, // suppression comment + c.getText(), // text of suppression comment (excluding delimiters) + c.getAnnotation(), // text of suppression annotation + c.getScope() // scope of suppression diff --git a/csharp/ql/src/Architecture/Dependencies/MutualDependency.ql b/csharp/ql/src/Architecture/Dependencies/MutualDependency.ql index 74587c408a8..5f5d58345a1 100644 --- a/csharp/ql/src/Architecture/Dependencies/MutualDependency.ql +++ b/csharp/ql/src/Architecture/Dependencies/MutualDependency.ql @@ -15,32 +15,27 @@ import semmle.code.csharp.metrics.Coupling /** inner is nested (possibly more than one level deep) within outer */ predicate nestedWithin(ValueOrRefType outer, NestedType inner) { - inner.getDeclaringType() = outer - or nestedWithin(outer, inner.getDeclaringType()) + inner.getDeclaringType() = outer or + nestedWithin(outer, inner.getDeclaringType()) } from ValueOrRefType t1, ValueOrRefType t2 where - t1 != t2 - and depends(t1, t2) - and depends(t2, t1) - + t1 != t2 and + depends(t1, t2) and + depends(t2, t1) and // PREVENT SYMMETRICAL RESULTS - and t1.getName() < t2.getName() - + t1.getName() < t2.getName() and // ADDITIONAL CONSTRAINTS - and t1.fromSource() - and t2.fromSource() - + t1.fromSource() and + t2.fromSource() and // EXCLUSIONS - and not - ( - nestedWithin(t1, t2) - or nestedWithin(t2, t1) - or t1.getName().toLowerCase().matches("%visitor%") - or t2.getName().toLowerCase().matches("%visitor%") - or t1.getAMember().getName().toLowerCase().matches("%visit%") - or t2.getAMember().getName().toLowerCase().matches("%visit%") + not ( + nestedWithin(t1, t2) or + nestedWithin(t2, t1) or + t1.getName().toLowerCase().matches("%visitor%") or + t2.getName().toLowerCase().matches("%visitor%") or + t1.getAMember().getName().toLowerCase().matches("%visit%") or + t2.getAMember().getName().toLowerCase().matches("%visit%") ) -select t1, "This type and type $@ are mutually dependent.", - t2, t2.getName() +select t1, "This type and type $@ are mutually dependent.", t2, t2.getName() diff --git a/csharp/ql/src/Architecture/Refactoring Opportunities/FeatureEnvy.ql b/csharp/ql/src/Architecture/Refactoring Opportunities/FeatureEnvy.ql index 32918dd0bb9..71af4b25bc7 100644 --- a/csharp/ql/src/Architecture/Refactoring Opportunities/FeatureEnvy.ql +++ b/csharp/ql/src/Architecture/Refactoring Opportunities/FeatureEnvy.ql @@ -11,31 +11,24 @@ * maintainability * modularity */ + import csharp Member getAUsedMember(Method m) { - exists(MemberAccess ma | - ma.getEnclosingCallable() = m | + exists(MemberAccess ma | ma.getEnclosingCallable() = m | result = ma.getTarget().getSourceDeclaration() ) or - exists(Call c | - c.getEnclosingCallable() = m | - result = c.getTarget().getSourceDeclaration() - ) + exists(Call c | c.getEnclosingCallable() = m | result = c.getTarget().getSourceDeclaration()) } int dependencyCount(Method source, RefType target) { result = strictcount(Member m | m = getAUsedMember(source) and m = target.getAMember()) } -predicate methodDependsOn(Method m, RefType target) { - exists(dependencyCount(m, target)) -} +predicate methodDependsOn(Method m, RefType target) { exists(dependencyCount(m, target)) } -predicate dependsOn(RefType source, RefType target) { - methodDependsOn(source.getAMethod(), target) -} +predicate dependsOn(RefType source, RefType target) { methodDependsOn(source.getAMethod(), target) } int selfDependencyCount(Method source) { result = sum(dependencyCount(source, source.getDeclaringType+())) @@ -44,12 +37,12 @@ int selfDependencyCount(Method source) { predicate dependsHighlyOn(Method source, RefType target, int selfCount, int depCount) { depCount = dependencyCount(source, target) and selfCount = selfDependencyCount(source) and - depCount > 2*selfCount and + depCount > 2 * selfCount and depCount > 4 } predicate query(Method m, RefType targetType, int selfCount, int depCount) { - exists (RefType sourceType | sourceType = m.getDeclaringType() | + exists(RefType sourceType | sourceType = m.getDeclaringType() | dependsHighlyOn(m, targetType, selfCount, depCount) and // Interfaces are depended upon by their very nature not targetType instanceof Interface and @@ -63,8 +56,7 @@ predicate query(Method m, RefType targetType, int selfCount, int depCount) { // Do not move between nested types not (sourceType.getDeclaringType*() = targetType or targetType.getDeclaringType*() = sourceType) and // Check that the target type already depends on every type used by the method - forall(RefType dependency | - methodDependsOn(m, dependency) | + forall(RefType dependency | methodDependsOn(m, dependency) | dependsOn(targetType, dependency) or targetType = dependency or dependency.getNamespace().hasName("System") @@ -73,10 +65,12 @@ predicate query(Method m, RefType targetType, int selfCount, int depCount) { } from Method m, RefType other, int selfCount, int depCount -where query(m, other, selfCount, depCount) and - // Don't include types that are used from many different places - we only highlight - // relatively local fixes that could reasonably be implemented. - count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10 -select m, "Method " + m.getName() + " is too closely tied to $@: " + depCount + - " dependencies to it, but only " + selfCount + " dependencies to its own type.", - other, other.getName() +where + query(m, other, selfCount, depCount) and + // Don't include types that are used from many different places - we only highlight + // relatively local fixes that could reasonably be implemented. + count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10 +select m, + "Method " + m.getName() + " is too closely tied to $@: " + depCount + + " dependencies to it, but only " + selfCount + " dependencies to its own type.", other, + other.getName() diff --git a/csharp/ql/src/Architecture/Refactoring Opportunities/InappropriateIntimacy.ql b/csharp/ql/src/Architecture/Refactoring Opportunities/InappropriateIntimacy.ql index 82aa1ee5c64..3e9ae20c97c 100644 --- a/csharp/ql/src/Architecture/Refactoring Opportunities/InappropriateIntimacy.ql +++ b/csharp/ql/src/Architecture/Refactoring Opportunities/InappropriateIntimacy.ql @@ -9,6 +9,7 @@ * @tags maintainability * modularity */ + import csharp predicate enclosingRefType(Variable v, RefType type) { @@ -45,16 +46,19 @@ predicate dependencyCount(RefType source, RefType target, int res) { exists(int varCount, int funCount | variableDependencyCount(source, target, varCount) and functionDependencyCount(source, target, funCount) and - res = varCount + funCount - and res > 15) + res = varCount + funCount and + res > 15 + ) } from RefType a, RefType b, int ca, int cb -where dependencyCount(a, b, ca) and - dependencyCount(b, a, cb) and - ca > 15 and - cb > 15 and - ca >= cb and - a != b -select a, "Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() + - " dependencies one way and " + cb.toString() + " the other).", b, b.getName() +where + dependencyCount(a, b, ca) and + dependencyCount(b, a, cb) and + ca > 15 and + cb > 15 and + ca >= cb and + a != b +select a, + "Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() + + " dependencies one way and " + cb.toString() + " the other).", b, b.getName() diff --git a/csharp/ql/src/Bad Practices/CallsUnmanagedCode.ql b/csharp/ql/src/Bad Practices/CallsUnmanagedCode.ql index 79352fe8aff..035e22c7d3e 100644 --- a/csharp/ql/src/Bad Practices/CallsUnmanagedCode.ql +++ b/csharp/ql/src/Bad Practices/CallsUnmanagedCode.ql @@ -12,7 +12,8 @@ import csharp from Class c, Method m, MethodCall call -where m.isExtern() - and m.getDeclaringType() = c - and call.getTarget() = m +where + m.isExtern() and + m.getDeclaringType() = c and + call.getTarget() = m select call, "Replace this call with a call to managed code if possible." diff --git a/csharp/ql/src/Bad Practices/CatchOfNullReferenceException.ql b/csharp/ql/src/Bad Practices/CatchOfNullReferenceException.ql index 4d53dbdaee6..59e35bb3cb5 100644 --- a/csharp/ql/src/Bad Practices/CatchOfNullReferenceException.ql +++ b/csharp/ql/src/Bad Practices/CatchOfNullReferenceException.ql @@ -9,6 +9,7 @@ * correctness * external/cwe/cwe-395 */ + import csharp from SpecificCatchClause scc diff --git a/csharp/ql/src/Bad Practices/Comments/CommentedOutCode.ql b/csharp/ql/src/Bad Practices/Comments/CommentedOutCode.ql index 8a007ff8a07..8b397c2351e 100644 --- a/csharp/ql/src/Bad Practices/Comments/CommentedOutCode.ql +++ b/csharp/ql/src/Bad Practices/Comments/CommentedOutCode.ql @@ -12,12 +12,10 @@ import csharp -class CommentedOutCode extends CommentBlock -{ - CommentedOutCode() - { +class CommentedOutCode extends CommentBlock { + CommentedOutCode() { not isXmlCommentBlock() and - 2*count(getAProbableCodeLine()) > count(getANonEmptyLine()) + 2 * count(getAProbableCodeLine()) > count(getANonEmptyLine()) } } diff --git a/csharp/ql/src/Bad Practices/Comments/TodoComments.ql b/csharp/ql/src/Bad Practices/Comments/TodoComments.ql index 59c327b0301..bb87724678f 100644 --- a/csharp/ql/src/Bad Practices/Comments/TodoComments.ql +++ b/csharp/ql/src/Bad Practices/Comments/TodoComments.ql @@ -9,6 +9,7 @@ * @tags maintainability * external/cwe/cwe-546 */ + import csharp from CommentLine c diff --git a/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql b/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql index fc6270dce0e..54aa25c369f 100644 --- a/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql +++ b/csharp/ql/src/Bad Practices/Control-Flow/ConstantCondition.ql @@ -11,6 +11,7 @@ * readability * external/cwe/cwe-835 */ + import csharp import semmle.code.csharp.commons.Assertions import semmle.code.csharp.commons.Constants @@ -28,13 +29,9 @@ abstract class ConstantCondition extends Expr { class ConstantBooleanCondition extends ConstantCondition { boolean b; - ConstantBooleanCondition() { - isConstantCondition(this, b) - } + ConstantBooleanCondition() { isConstantCondition(this, b) } - override string getMessage() { - result = "Condition always evaluates to '" + b + "'." - } + override string getMessage() { result = "Condition always evaluates to '" + b + "'." } override predicate isWhiteListed() { // E.g. `x ?? false` @@ -60,9 +57,7 @@ class ConstantIfCondition extends ConstantBooleanCondition { /** A constant loop condition. */ class ConstantLoopCondition extends ConstantBooleanCondition { - ConstantLoopCondition() { - this = any(LoopStmt ls).getCondition() - } + ConstantLoopCondition() { this = any(LoopStmt ls).getCondition() } override predicate isWhiteListed() { // Clearly intentional infinite loops are allowed @@ -75,10 +70,8 @@ class ConstantNullnessCondition extends ConstantCondition { boolean b; ConstantNullnessCondition() { - forex(ControlFlow::Node cfn | - cfn = this.getAControlFlowNode() | - exists(ControlFlow::SuccessorTypes::NullnessSuccessor t | - exists(cfn.getASuccessorByType(t)) | + forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() | + exists(ControlFlow::SuccessorTypes::NullnessSuccessor t | exists(cfn.getASuccessorByType(t)) | b = t.getValue() ) and strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1 @@ -86,10 +79,9 @@ class ConstantNullnessCondition extends ConstantCondition { } override string getMessage() { - if b = true then - result = "Expression is always 'null'." - else - result = "Expression is never 'null'." + if b = true + then result = "Expression is always 'null'." + else result = "Expression is never 'null'." } } @@ -98,10 +90,8 @@ class ConstantMatchingCondition extends ConstantCondition { boolean b; ConstantMatchingCondition() { - forex(ControlFlow::Node cfn | - cfn = this.getAControlFlowNode() | - exists(ControlFlow::SuccessorTypes::MatchingSuccessor t | - exists(cfn.getASuccessorByType(t)) | + forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() | + exists(ControlFlow::SuccessorTypes::MatchingSuccessor t | exists(cfn.getASuccessorByType(t)) | b = t.getValue() ) and strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1 @@ -109,15 +99,13 @@ class ConstantMatchingCondition extends ConstantCondition { } override string getMessage() { - if b = true then - result = "Pattern always matches." - else - result = "Pattern never matches." + if b = true then result = "Pattern always matches." else result = "Pattern never matches." } } from ConstantCondition c, string msg -where msg = c.getMessage() - and not c.isWhiteListed() - and not isExprInAssertion(c) +where + msg = c.getMessage() and + not c.isWhiteListed() and + not isExprInAssertion(c) select c, msg diff --git a/csharp/ql/src/Bad Practices/Declarations/EmptyInterface.ql b/csharp/ql/src/Bad Practices/Declarations/EmptyInterface.ql index 8b58e6b0b45..015b172db90 100644 --- a/csharp/ql/src/Bad Practices/Declarations/EmptyInterface.ql +++ b/csharp/ql/src/Bad Practices/Declarations/EmptyInterface.ql @@ -13,7 +13,8 @@ import csharp from Interface i -where not exists(i.getAMember()) - and i.isSourceDeclaration() - and count(Interface base | i.getABaseInterface() = base) <= 1 +where + not exists(i.getAMember()) and + i.isSourceDeclaration() and + count(Interface base | i.getABaseInterface() = base) <= 1 select i, "Interface '" + i.getName() + "' does not declare any members." diff --git a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql index bb4e6e10131..d3b9135df6e 100644 --- a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql +++ b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql @@ -9,9 +9,10 @@ * @tags maintainability * readability */ + import csharp -pragma [noinline] +pragma[noinline] private string localVarInType(ValueOrRefType t, LocalScopeVariable v) { v.getCallable().getDeclaringType() = t and result = v.getName() and @@ -28,12 +29,10 @@ private string memberInType(ValueOrRefType t, Member m) { } private predicate acceptableShadowing(LocalScopeVariable v, Member m) { - exists(ValueOrRefType t | - localVarInType(t, v) = memberInType(t, m) | + exists(ValueOrRefType t | localVarInType(t, v) = memberInType(t, m) | // If the callable declaring the local also accesses the shadowed member // using an explicit `this` qualifier, the shadowing is likely deliberate. - exists(MemberAccess ma | - ma.getTarget() = m | + exists(MemberAccess ma | ma.getTarget() = m | ma.getEnclosingCallable() = v.getCallable() and ma.targetIsLocalInstance() and not ma.getQualifier().isImplicit() @@ -49,7 +48,9 @@ private predicate shadowing(ValueOrRefType t, LocalScopeVariable v, Member m) { } from LocalScopeVariable v, Callable c, ValueOrRefType t, Member m -where c = v.getCallable() - and shadowing(t, v, m) - and (c.(Modifiable).isStatic() implies m.isStatic()) -select v, "Local scope variable '" + v.getName() + "' shadows $@.", m, t.getName() + "." + m.getName() +where + c = v.getCallable() and + shadowing(t, v, m) and + (c.(Modifiable).isStatic() implies m.isStatic()) +select v, "Local scope variable '" + v.getName() + "' shadows $@.", m, + t.getName() + "." + m.getName() diff --git a/csharp/ql/src/Bad Practices/Declarations/NoConstantsOnly.ql b/csharp/ql/src/Bad Practices/Declarations/NoConstantsOnly.ql index 8bd706c7347..896b7804662 100644 --- a/csharp/ql/src/Bad Practices/Declarations/NoConstantsOnly.ql +++ b/csharp/ql/src/Bad Practices/Declarations/NoConstantsOnly.ql @@ -9,6 +9,7 @@ * @tags maintainability * modularity */ + import csharp class ConstantField extends Field { @@ -20,11 +21,11 @@ class ConstantField extends Field { } from Class c -where c.isSourceDeclaration() - and c.isAbstract() - and c.getAMember() instanceof ConstantField - and forex(Member m | - m = c.getAMember() | +where + c.isSourceDeclaration() and + c.isAbstract() and + c.getAMember() instanceof ConstantField and + forex(Member m | m = c.getAMember() | m instanceof ConstantField or m instanceof Constructor ) diff --git a/csharp/ql/src/Bad Practices/Declarations/TooManyRefParameters.ql b/csharp/ql/src/Bad Practices/Declarations/TooManyRefParameters.ql index 2249dfdefae..048aad57978 100644 --- a/csharp/ql/src/Bad Practices/Declarations/TooManyRefParameters.ql +++ b/csharp/ql/src/Bad Practices/Declarations/TooManyRefParameters.ql @@ -13,7 +13,9 @@ import csharp from Method m, int n -where m.isSourceDeclaration() - and n = count(Parameter p | p = m.getAParameter() and p.isRef()) - and n > 2 -select m, "Method '" + m.getName() + "' has " + n + " 'ref' parameters and might be hard to understand." +where + m.isSourceDeclaration() and + n = count(Parameter p | p = m.getAParameter() and p.isRef()) and + n > 2 +select m, + "Method '" + m.getName() + "' has " + n + " 'ref' parameters and might be hard to understand." diff --git a/csharp/ql/src/Bad Practices/EmptyCatchBlock.ql b/csharp/ql/src/Bad Practices/EmptyCatchBlock.ql index b682722ab53..144d53dc61f 100644 --- a/csharp/ql/src/Bad Practices/EmptyCatchBlock.ql +++ b/csharp/ql/src/Bad Practices/EmptyCatchBlock.ql @@ -11,9 +11,11 @@ * external/cwe/cwe-390 * external/cwe/cwe-391 */ + import csharp from CatchClause cc -where cc.getBlock().isEmpty() -and not exists(CommentBlock cb | cb.getParent()=cc.getBlock()) +where + cc.getBlock().isEmpty() and + not exists(CommentBlock cb | cb.getParent() = cc.getBlock()) select cc, "Poor error handling: empty catch block." diff --git a/csharp/ql/src/Bad Practices/ErroneousClassCompare.ql b/csharp/ql/src/Bad Practices/ErroneousClassCompare.ql index 628547d34bc..134d612979b 100644 --- a/csharp/ql/src/Bad Practices/ErroneousClassCompare.ql +++ b/csharp/ql/src/Bad Practices/ErroneousClassCompare.ql @@ -9,31 +9,28 @@ * correctness * external/cwe/cwe-486 */ + import csharp import semmle.code.csharp.commons.ComparisonTest import semmle.code.csharp.frameworks.System -ComparisonTest getComparisonTest(Expr e) { - result.getExpr() = e -} +ComparisonTest getComparisonTest(Expr e) { result.getExpr() = e } class StringComparison extends Expr { StringComparison() { - exists(ComparisonTest ct | - ct = getComparisonTest(this) | + exists(ComparisonTest ct | ct = getComparisonTest(this) | ct.getComparisonKind().isEquality() and ct.getFirstArgument().stripCasts().getType() instanceof StringType and ct.getSecondArgument().stripCasts().getType() instanceof StringType ) } - Expr getAnOperand() { - result = getComparisonTest(this).getAnArgument() - } + Expr getAnOperand() { result = getComparisonTest(this).getAnArgument() } } from StringComparison sc, PropertyAccess pa -where sc.getAnOperand() instanceof StringLiteral - and sc.getAnOperand() = pa - and pa.getTarget() = any(SystemTypeClass c).getFullNameProperty() +where + sc.getAnOperand() instanceof StringLiteral and + sc.getAnOperand() = pa and + pa.getTarget() = any(SystemTypeClass c).getFullNameProperty() select sc, "Erroneous class compare." diff --git a/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.ql b/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.ql index 7639863fdd7..5d765fa2640 100644 --- a/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.ql +++ b/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.ql @@ -12,6 +12,7 @@ * modularity * external/cwe/cwe-485 */ + import csharp import semmle.code.csharp.frameworks.system.Collections import semmle.code.csharp.frameworks.system.collections.Generic @@ -19,8 +20,7 @@ import semmle.code.csharp.frameworks.system.collections.Generic /** A collection interface. */ class CollectionInterface extends Interface { CollectionInterface() { - exists(Interface i | - i = this.getABaseInterface*() | + exists(Interface i | i = this.getABaseInterface*() | i instanceof SystemCollectionsICollectionInterface or i.getSourceDeclaration() instanceof SystemCollectionsGenericICollectionInterface or i instanceof SystemCollectionsIEnumerableInterface or @@ -30,8 +30,10 @@ class CollectionInterface extends Interface { } from CastExpr e, Class c, CollectionInterface i -where e.getType() = c - and e.getExpr().getType() = i - and c.isImplicitlyConvertibleTo(i) -select e, "Questionable cast from abstract '" + i.getName() - + "' to concrete implementation '" + c.getName() + "'." +where + e.getType() = c and + e.getExpr().getType() = i and + c.isImplicitlyConvertibleTo(i) +select e, + "Questionable cast from abstract '" + i.getName() + "' to concrete implementation '" + c.getName() + + "'." diff --git a/csharp/ql/src/Bad Practices/Implementation Hiding/ExposeRepresentation.ql b/csharp/ql/src/Bad Practices/Implementation Hiding/ExposeRepresentation.ql index b46189aa587..3847eae6e82 100644 --- a/csharp/ql/src/Bad Practices/Implementation Hiding/ExposeRepresentation.ql +++ b/csharp/ql/src/Bad Practices/Implementation Hiding/ExposeRepresentation.ql @@ -9,6 +9,7 @@ * @tags reliability * external/cwe/cwe-485 */ + import csharp import semmle.code.csharp.commons.Collections import DataFlow @@ -31,13 +32,9 @@ predicate returnsCollection(Callable c, Field f) { predicate mayWriteToCollection(Expr modified) { modified instanceof CollectionModificationAccess or - exists(Expr mid | - mayWriteToCollection(mid) | - localFlow(exprNode(modified), exprNode(mid)) - ) + exists(Expr mid | mayWriteToCollection(mid) | localFlow(exprNode(modified), exprNode(mid))) or - exists(MethodCall mid, Callable c | - mayWriteToCollection(mid) | + exists(MethodCall mid, Callable c | mayWriteToCollection(mid) | mid.getTarget() = c and c.canReturn(modified) ) @@ -49,16 +46,12 @@ predicate modificationAfter(Expr before, Expr after) { } VariableAccess varPassedInto(Callable c, Parameter p) { - exists(Call call | - call.getTarget() = c | - call.getArgumentForParameter(p) = result - ) + exists(Call call | call.getTarget() = c | call.getArgumentForParameter(p) = result) } predicate exposesByReturn(Callable c, Field f, Expr why, string whyText) { returnsCollection(c, f) and - exists(MethodCall ma | - ma.getTarget() = c | + exists(MethodCall ma | ma.getTarget() = c | mayWriteToCollection(ma) and why = ma and whyText = "after this call to " + c.getName() @@ -75,8 +68,9 @@ predicate exposesByStore(Callable c, Field f, Expr why, string whyText) { } from Callable c, Field f, Expr why, string whyText -where exposesByReturn(c, f, why, whyText) or - exposesByStore(c, f, why, whyText) -select c, "'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() + - "'. The value may be modified $@.", - why.getLocation(), whyText +where + exposesByReturn(c, f, why, whyText) or + exposesByStore(c, f, why, whyText) +select c, + "'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() + + "'. The value may be modified $@.", why.getLocation(), whyText diff --git a/csharp/ql/src/Bad Practices/Implementation Hiding/StaticArray.ql b/csharp/ql/src/Bad Practices/Implementation Hiding/StaticArray.ql index 29a60defcdc..1814ed703b7 100644 --- a/csharp/ql/src/Bad Practices/Implementation Hiding/StaticArray.ql +++ b/csharp/ql/src/Bad Practices/Implementation Hiding/StaticArray.ql @@ -10,31 +10,32 @@ * modularity * external/cwe/cwe-582 */ + import csharp predicate nonEmptyArrayLiteralOrNull(Expr e) { e = any(ArrayCreation arr | - exists(arr.getInitializer().getAnElement()) - or - not arr.getALengthArgument().getValue() = "0" - ) + exists(arr.getInitializer().getAnElement()) + or + not arr.getALengthArgument().getValue() = "0" + ) or e instanceof NullLiteral or e = any(ConditionalExpr cond | - nonEmptyArrayLiteralOrNull(cond.getThen()) and - nonEmptyArrayLiteralOrNull(cond.getElse()) - ) + nonEmptyArrayLiteralOrNull(cond.getThen()) and + nonEmptyArrayLiteralOrNull(cond.getElse()) + ) } from Field f -where f.isPublic() - and f.isStatic() - and f.isReadOnly() - and f.getType() instanceof ArrayType - and f.fromSource() - and forall(AssignableDefinition def | - def.getTarget() = f | +where + f.isPublic() and + f.isStatic() and + f.isReadOnly() and + f.getType() instanceof ArrayType and + f.fromSource() and + forall(AssignableDefinition def | def.getTarget() = f | nonEmptyArrayLiteralOrNull(def.getSource()) ) select f, "The array constant '" + f.getName() + "' is vulnerable to mutation." diff --git a/csharp/ql/src/Bad Practices/LeftoverDebugCode.ql b/csharp/ql/src/Bad Practices/LeftoverDebugCode.ql index 528d74603ae..c4fdee86eb8 100644 --- a/csharp/ql/src/Bad Practices/LeftoverDebugCode.ql +++ b/csharp/ql/src/Bad Practices/LeftoverDebugCode.ql @@ -10,11 +10,15 @@ * frameworks/asp.net * external/cwe/cwe-489 */ + import csharp import semmle.code.csharp.commons.Util from MainMethod m -where m.fromSource() - and exists(UsingNamespaceDirective u | u.getFile() = m.getFile() - and u.getImportedNamespace().hasQualifiedName("System.Web")) +where + m.fromSource() and + exists(UsingNamespaceDirective u | + u.getFile() = m.getFile() and + u.getImportedNamespace().hasQualifiedName("System.Web") + ) select m, "Remove debug code if your ASP.NET application is in production." diff --git a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsNumbers.ql b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsNumbers.ql index d9b947a29d9..a74de5a5878 100644 --- a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsNumbers.ql +++ b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsNumbers.ql @@ -8,15 +8,15 @@ * @tags changeability * maintainability */ + import csharp import MagicConstants -predicate selection(Element e, string msg) { - magicConstant(e, msg) -} +predicate selection(Element e, string msg) { magicConstant(e, msg) } from Literal e, string msg -where selection(e, msg) - and isNumber(e) - and not exists(Field f | f.getInitializer() = e) +where + selection(e, msg) and + isNumber(e) and + not exists(Field f | f.getInitializer() = e) select e, msg diff --git a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsString.ql b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsString.ql index e3d97a68aa1..628fabc2008 100644 --- a/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsString.ql +++ b/csharp/ql/src/Bad Practices/Magic Constants/MagicConstantsString.ql @@ -11,9 +11,7 @@ import MagicConstants -predicate selection(Element e, string msg) { - magicConstant(e, msg) -} +predicate selection(Element e, string msg) { magicConstant(e, msg) } from StringLiteral e, string msg where selection(e, msg) diff --git a/csharp/ql/src/Bad Practices/Magic Constants/MagicNumbersUseConstant.ql b/csharp/ql/src/Bad Practices/Magic Constants/MagicNumbersUseConstant.ql index 96bc5d33095..f623c731166 100644 --- a/csharp/ql/src/Bad Practices/Magic Constants/MagicNumbersUseConstant.ql +++ b/csharp/ql/src/Bad Practices/Magic Constants/MagicNumbersUseConstant.ql @@ -12,6 +12,7 @@ import MagicConstants from Literal magicLiteral, string message, Field constant -where isNumber(magicLiteral) - and literalInsteadOfConstant(magicLiteral, _, message, constant) +where + isNumber(magicLiteral) and + literalInsteadOfConstant(magicLiteral, _, message, constant) select magicLiteral, message, constant, constant.getName() diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingMethodNames.ql b/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingMethodNames.ql index 532563ade94..5e3f39d7a87 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingMethodNames.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingMethodNames.ql @@ -9,6 +9,7 @@ * readability * naming */ + import csharp predicate typeWithConfusingName(ValueOrRefType type) { @@ -16,11 +17,12 @@ predicate typeWithConfusingName(ValueOrRefType type) { } from Method m, Method n, ValueOrRefType type -where typeWithConfusingName(type) - and type.fromSource() - and m = type.getAMethod() - and n = type.getAMethod() - and m != n - and m.getName().toLowerCase() = n.getName().toLowerCase() - and m.getName() < n.getName() +where + typeWithConfusingName(type) and + type.fromSource() and + m = type.getAMethod() and + n = type.getAMethod() and + m != n and + m.getName().toLowerCase() = n.getName().toLowerCase() and + m.getName() < n.getName() select m, "Confusing method name, compare with $@.", n, n.getName() diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql b/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql index 6005281bc3a..37bbae644ab 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ConfusingOverridesNames.ql @@ -10,15 +10,18 @@ * readability * naming */ + import csharp predicate hasSubtypeStar(RefType t, RefType u) { - t = u - or u.getABaseType+() = t + t = u or + u.getABaseType+() = t } -/** for each class, get all methods from this class or its - superclasses, with their names in lowercase */ +/** + * for each class, get all methods from this class or its + * superclasses, with their names in lowercase + */ predicate methodNames(RefType t, Method m, string lowercase) { exists(RefType t2 | m.getDeclaringType() = t2 and @@ -28,8 +31,10 @@ predicate methodNames(RefType t, Method m, string lowercase) { lowercase.length() > 1 } -/** For each class, find the pairs of methods that - are candidates for being confusing in this class */ +/** + * For each class, find the pairs of methods that + * are candidates for being confusing in this class + */ predicate confusing(Method m1, Method m2) { exists(RefType t, string lower | methodNames(t, m1, lower) and @@ -38,33 +43,37 @@ 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 - m1.getDeclaringType() != m2.getDeclaringType() and - ( - m1.isStatic() and m2.isStatic() - or - not m1.isStatic() and not m2.isStatic() - ) and - not exists(Method mid | - confusing(m1, mid) and - mid.getDeclaringType().getABaseType+() = m2.getDeclaringType() - ) and - not exists(Method notConfusing | - notConfusing.getDeclaringType() = m1.getDeclaringType() and - notConfusing.getName() = m2.getName() - ) and - m1.fromSource() -select m1, "confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " - + m2.getName() + " in " + m2.getDeclaringType().getName() + "." +where + confusing(m1, m2) and + m1.getDeclaringType() != m2.getDeclaringType() and + ( + m1.isStatic() and m2.isStatic() + or + not m1.isStatic() and not m2.isStatic() + ) and + not exists(Method mid | + confusing(m1, mid) and + mid.getDeclaringType().getABaseType+() = m2.getDeclaringType() + ) and + not exists(Method notConfusing | + notConfusing.getDeclaringType() = m1.getDeclaringType() and + notConfusing.getName() = m2.getName() + ) and + m1.fromSource() +select m1, + "confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " + + m2.getName() + " in " + m2.getDeclaringType().getName() + "." diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ConstantNaming.ql b/csharp/ql/src/Bad Practices/Naming Conventions/ConstantNaming.ql index 612a99a041c..311b12017d3 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ConstantNaming.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ConstantNaming.ql @@ -23,13 +23,12 @@ class PublicConstantField extends Field { from PublicConstantField f where // The first character of the field's name is not uppercase. - not(f.getName().charAt(0).isUppercase()) + not (f.getName().charAt(0).isUppercase()) or ( // The field's name is uppercase. - f.getName().isUppercase() - + f.getName().isUppercase() and // The field's name is at least 4 characters long. - and f.getName().length() >= 4 + f.getName().length() >= 4 ) select f, "Public static read-only fields should be named in PascalCase." diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql b/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql index 4c0814f6ae8..48bd1f8a3b2 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/ControlNamePrefixes.ql @@ -12,51 +12,89 @@ import csharp string prefix(string typename) { - (typename = "System.Web.UI.WebControls.Label" and result = "lbl") or - (typename = "System.Web.UI.WebControls.TextBox" and result = "txt") or - (typename = "System.Web.UI.WebControls.Button" and result = "btn") or - (typename = "System.Web.UI.WebControls.LinkButton" and result = "btn") or - (typename = "System.Web.UI.WebControls.ImageButton" and result = "ibtn") or - (typename = "System.Web.UI.WebControls.Hyperlink" and result = "hpl") or - (typename = "System.Web.UI.WebControls.DropDownList" and result = "cmb") or - (typename = "System.Web.UI.WebControls.ListBox" and result = "lst") or - (typename = "System.Web.UI.WebControls.Datagrid" and result = "dgr") or - (typename = "System.Web.UI.WebControls.Datalist" and result = "dtl") or - (typename = "System.Web.UI.WebControls.Repeater" and result = "rpt") or - (typename = "System.Web.UI.WebControls.CheckBox" and result = "chk") or - (typename = "System.Web.UI.WebControls.CheckBoxList" and result = "chklst") or - (typename = "System.Web.UI.WebControls.RadioButtonList" and result = "radlst") or - (typename = "System.Web.UI.WebControls.RadioButton" and result = "rad") or - (typename = "System.Web.UI.WebControls.Image" and result = "img") or - (typename = "System.Web.UI.WebControls.Panel" and result = "pnl") or - (typename = "System.Web.UI.WebControls.PlaceHolder" and result = "plh") or - (typename = "System.Web.UI.WebControls.Calendar" and result = "cal") or - (typename = "System.Web.UI.WebControls.AdRotator" and result = "adr") or - (typename = "System.Web.UI.WebControls.Table" and result = "tbl") or - (typename = "System.Web.UI.WebControls.RequiredFieldValidator" and result = "rfv") or - (typename = "System.Web.UI.WebControls.CompareValidator" and result = "cmv") or - (typename = "System.Web.UI.WebControls.RegularExpressionValidator" and result = "rev") or - (typename = "System.Web.UI.WebControls.CustomValidator" and result = "csv") or - (typename = "System.Web.UI.WebControls.ValidationSummary" and result = "vsm") or - (typename = "System.Web.UI.WebControls.XML" and result = "xml") or - (typename = "System.Web.UI.WebControls.Literal" and result = "lit") or - (typename = "System.Web.UI.WebControls.Form" and result = "frm") or - (typename = "System.Web.UI.WebControls.Frame" and result = "fra") or - (typename = "System.Web.UI.WebControls.CrystalReportViewer" and result = "crvr") or - - (typename = "System.Web.UI.HtmlControls.TextArea" and result = "txa") or - (typename = "System.Web.UI.HtmlControls.FileField" and result = "fle") or - (typename = "System.Web.UI.HtmlControls.PasswordField" and result = "pwd") or - (typename = "System.Web.UI.HtmlControls.Hidden" and result = "hdn") or - (typename = "System.Web.UI.HtmlControls.Table" and result = "tbl") or - (typename = "System.Web.UI.HtmlControls.FlowLayoutPanel" and result = "flp") or - (typename = "System.Web.UI.HtmlControls.GridLayoutPanel" and result = "glp") or + (typename = "System.Web.UI.WebControls.Label" and result = "lbl") + or + (typename = "System.Web.UI.WebControls.TextBox" and result = "txt") + or + (typename = "System.Web.UI.WebControls.Button" and result = "btn") + or + (typename = "System.Web.UI.WebControls.LinkButton" and result = "btn") + or + (typename = "System.Web.UI.WebControls.ImageButton" and result = "ibtn") + or + (typename = "System.Web.UI.WebControls.Hyperlink" and result = "hpl") + or + (typename = "System.Web.UI.WebControls.DropDownList" and result = "cmb") + or + (typename = "System.Web.UI.WebControls.ListBox" and result = "lst") + or + (typename = "System.Web.UI.WebControls.Datagrid" and result = "dgr") + or + (typename = "System.Web.UI.WebControls.Datalist" and result = "dtl") + or + (typename = "System.Web.UI.WebControls.Repeater" and result = "rpt") + or + (typename = "System.Web.UI.WebControls.CheckBox" and result = "chk") + or + (typename = "System.Web.UI.WebControls.CheckBoxList" and result = "chklst") + or + (typename = "System.Web.UI.WebControls.RadioButtonList" and result = "radlst") + or + (typename = "System.Web.UI.WebControls.RadioButton" and result = "rad") + or + (typename = "System.Web.UI.WebControls.Image" and result = "img") + or + (typename = "System.Web.UI.WebControls.Panel" and result = "pnl") + or + (typename = "System.Web.UI.WebControls.PlaceHolder" and result = "plh") + or + (typename = "System.Web.UI.WebControls.Calendar" and result = "cal") + or + (typename = "System.Web.UI.WebControls.AdRotator" and result = "adr") + or + (typename = "System.Web.UI.WebControls.Table" and result = "tbl") + or + (typename = "System.Web.UI.WebControls.RequiredFieldValidator" and result = "rfv") + or + (typename = "System.Web.UI.WebControls.CompareValidator" and result = "cmv") + or + (typename = "System.Web.UI.WebControls.RegularExpressionValidator" and result = "rev") + or + (typename = "System.Web.UI.WebControls.CustomValidator" and result = "csv") + or + (typename = "System.Web.UI.WebControls.ValidationSummary" and result = "vsm") + or + (typename = "System.Web.UI.WebControls.XML" and result = "xml") + or + (typename = "System.Web.UI.WebControls.Literal" and result = "lit") + or + (typename = "System.Web.UI.WebControls.Form" and result = "frm") + or + (typename = "System.Web.UI.WebControls.Frame" and result = "fra") + or + (typename = "System.Web.UI.WebControls.CrystalReportViewer" and result = "crvr") + or + (typename = "System.Web.UI.HtmlControls.TextArea" and result = "txa") + or + (typename = "System.Web.UI.HtmlControls.FileField" and result = "fle") + or + (typename = "System.Web.UI.HtmlControls.PasswordField" and result = "pwd") + or + (typename = "System.Web.UI.HtmlControls.Hidden" and result = "hdn") + or + (typename = "System.Web.UI.HtmlControls.Table" and result = "tbl") + or + (typename = "System.Web.UI.HtmlControls.FlowLayoutPanel" and result = "flp") + or + (typename = "System.Web.UI.HtmlControls.GridLayoutPanel" and result = "glp") + or (typename = "System.Web.UI.HtmlControls.HorizontalRule" and result = "hr") } from Field f, RefType t, string name, string prefix -where f.getType() = t - and f.getName() = name - and prefix = prefix(t.getQualifiedName()) - and not name.matches(prefix + "%") +where + f.getType() = t and + f.getName() = name and + prefix = prefix(t.getQualifiedName()) and + not name.matches(prefix + "%") select f, "This field should have the prefix '" + prefix + "' to match its types." diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql index 28a238febba..f944bc49d2d 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/DefaultControlNames.ql @@ -1,7 +1,7 @@ /** * @name Windows controls with generated names * @description Replacing the generated names in windows forms with meaningful names - makes it easier for other developers to understand the code. + * makes it easier for other developers to understand the code. * @kind problem * @problem.severity recommendation * @precision medium @@ -9,10 +9,10 @@ * @tags readability * naming */ + import csharp -predicate controlName(string prefix) -{ +predicate controlName(string prefix) { prefix = "[Ll]abel" or prefix = "[Bb]utton" or prefix = "[Pp]anel" or @@ -28,13 +28,15 @@ predicate controlName(string prefix) predicate usedInHumanWrittenCode(Field f) { exists(File file | f.getAnAccess().getFile() = file and - not file.getBaseName().toLowerCase().matches("%.designer.cs")) + not file.getBaseName().toLowerCase().matches("%.designer.cs") + ) } from Field field, ValueOrRefType widget, string prefix -where widget.getABaseType*().hasQualifiedName("System.Windows.Forms.Control") - and field.getType() = widget - and field.getName().regexpMatch(prefix + "[0-9]+") - and controlName(prefix) - and usedInHumanWrittenCode(field) +where + widget.getABaseType*().hasQualifiedName("System.Windows.Forms.Control") and + field.getType() = widget and + field.getName().regexpMatch(prefix + "[0-9]+") and + controlName(prefix) and + usedInHumanWrittenCode(field) select field, "Control '" + field.getName() + "' should have a meaningful name." diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/FieldMasksSuperField.ql b/csharp/ql/src/Bad Practices/Naming Conventions/FieldMasksSuperField.ql index 37804e42ba2..3515e710d82 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/FieldMasksSuperField.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/FieldMasksSuperField.ql @@ -11,6 +11,7 @@ * readability * naming */ + import csharp class VisibleInstanceField extends Field { @@ -20,14 +21,16 @@ class VisibleInstanceField extends Field { } } -from RefType type, RefType supertype, - VisibleInstanceField masked, VisibleInstanceField masking -where type.getABaseType+() =supertype and - masking.getDeclaringType() = type and - masked.getDeclaringType() = supertype and - masked.getName() = masking.getName() and - // exclude intentional masking - not exists(FieldAccess va | va.getTarget() = masked and - va.getQualifier() instanceof BaseAccess) and - type.fromSource() +from RefType type, RefType supertype, VisibleInstanceField masked, VisibleInstanceField masking +where + type.getABaseType+() = supertype and + masking.getDeclaringType() = type and + masked.getDeclaringType() = supertype and + masked.getName() = masking.getName() and + // exclude intentional masking + not exists(FieldAccess va | + va.getTarget() = masked and + va.getQualifier() instanceof BaseAccess + ) and + type.fromSource() select masking, "This field shadows another field in a superclass." diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/SameNameAsSuper.ql b/csharp/ql/src/Bad Practices/Naming Conventions/SameNameAsSuper.ql index f4c7b83b8f3..83c795a3985 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/SameNameAsSuper.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/SameNameAsSuper.ql @@ -9,10 +9,12 @@ * readability * naming */ + import csharp from RefType sub, RefType sup -where sub.getABaseType() = sup and - sub.getName() = sup.getName() and - sub.fromSource() +where + sub.getABaseType() = sup and + sub.getName() = sup.getName() and + sub.fromSource() select sub, "Class has the same name as its base class." diff --git a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql index 90b31d1886e..f161edda6c4 100644 --- a/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql +++ b/csharp/ql/src/Bad Practices/Naming Conventions/VariableNameTooShort.ql @@ -10,50 +10,56 @@ import csharp -predicate sourceFile(File f) -{ +predicate sourceFile(File f) { f.fromSource() and not f.getAbsolutePath() = "null" and not f.getAbsolutePath().matches("%ActivXTabControl%.cs") } from Variable variable, string name -where name = variable.getName() - and variable.fromSource() - and sourceFile(variable.getFile()) - and not allowedName(name) - and not allowedVariable(variable) -// -// Adjustable parameter: -// - and name.length() < 3 +where + name = variable.getName() and + variable.fromSource() and + sourceFile(variable.getFile()) and + not allowedName(name) and + not allowedVariable(variable) and + // + // Adjustable parameter: + // + name.length() < 3 // select variable, "Variable name '" + name + "' is too short." // // Adjustable: acceptable short names // -predicate allowedName(string name) -{ - name = "url" or name = "cmd" or name = "UK" or name = "uri" or - name = "top" or name = "row" or name = "pin" or name = "log" or - name = "key" or name = "_" +predicate allowedName(string name) { + name = "url" or + name = "cmd" or + name = "UK" or + name = "uri" or + name = "top" or + name = "row" or + name = "pin" or + name = "log" or + name = "key" or + name = "_" } // // Adjustable: variables that are allowed to have short names // -predicate allowedVariable(Variable variable) -{ - exists(Parameter param | variable = param and +predicate allowedVariable(Variable variable) { + exists(Parameter param | + variable = param and not exists(param.getAnAccess()) and - param.getType().getName().matches("%EventArgs")) - or - exists(LocalVariable local | variable = local and - local.getVariableDeclExpr().getParent() instanceof CatchClause) - or - exists(Call c, LambdaExpr le | - le.getAParameter() = variable | - c.getAnArgument() = le + param.getType().getName().matches("%EventArgs") ) + or + exists(LocalVariable local | + variable = local and + local.getVariableDeclExpr().getParent() instanceof CatchClause + ) + or + exists(Call c, LambdaExpr le | le.getAParameter() = variable | c.getAnArgument() = le) } diff --git a/csharp/ql/src/Bad Practices/UnmanagedCodeCheck.ql b/csharp/ql/src/Bad Practices/UnmanagedCodeCheck.ql index 5ba0d2458a4..6a59fa1d1fa 100644 --- a/csharp/ql/src/Bad Practices/UnmanagedCodeCheck.ql +++ b/csharp/ql/src/Bad Practices/UnmanagedCodeCheck.ql @@ -12,6 +12,7 @@ import csharp from Class c, Method m -where m.isExtern() - and m.getDeclaringType() = c +where + m.isExtern() and + m.getDeclaringType() = c select m, "Minimise the use of unmanaged code." diff --git a/csharp/ql/src/Bad Practices/UseOfHtmlInputHidden.ql b/csharp/ql/src/Bad Practices/UseOfHtmlInputHidden.ql index 2dc36d9e29e..93c3850e103 100644 --- a/csharp/ql/src/Bad Practices/UseOfHtmlInputHidden.ql +++ b/csharp/ql/src/Bad Practices/UseOfHtmlInputHidden.ql @@ -10,6 +10,7 @@ * frameworks/asp.net * external/cwe/cwe-472 */ + import csharp from ObjectCreation oc diff --git a/csharp/ql/src/Bad Practices/UseOfSystemOutputStream.ql b/csharp/ql/src/Bad Practices/UseOfSystemOutputStream.ql index 63824b15d44..05424066c41 100644 --- a/csharp/ql/src/Bad Practices/UseOfSystemOutputStream.ql +++ b/csharp/ql/src/Bad Practices/UseOfSystemOutputStream.ql @@ -7,17 +7,22 @@ * @id cs/console-output * @tags maintainability */ + import csharp import semmle.code.csharp.commons.Util predicate isConsoleOutRedefinedSomewhere() { - exists(MethodCall mc | mc.getTarget().hasName("SetOut") and - mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")) + exists(MethodCall mc | + mc.getTarget().hasName("SetOut") and + mc.getTarget().getDeclaringType().hasQualifiedName("System.Console") + ) } predicate isConsoleErrorRedefinedSomewhere() { - exists(MethodCall mc | mc.getTarget().hasName("SetError") and - mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")) + exists(MethodCall mc | + mc.getTarget().hasName("SetError") and + mc.getTarget().getDeclaringType().hasQualifiedName("System.Console") + ) } predicate isCallToConsoleWrite(MethodCall mc) { @@ -36,8 +41,13 @@ predicate isAccessToConsoleError(PropertyAccess pa) { } from Expr e -where (isCallToConsoleWrite(e) and not isConsoleOutRedefinedSomewhere() - or isAccessToConsoleOut(e) and not isConsoleOutRedefinedSomewhere() - or isAccessToConsoleError(e) and not isConsoleErrorRedefinedSomewhere()) - and not e.getEnclosingCallable() instanceof MainMethod +where + ( + isCallToConsoleWrite(e) and not isConsoleOutRedefinedSomewhere() + or + isAccessToConsoleOut(e) and not isConsoleOutRedefinedSomewhere() + or + isAccessToConsoleError(e) and not isConsoleErrorRedefinedSomewhere() + ) and + not e.getEnclosingCallable() instanceof MainMethod select e, "Poor logging: use of system output stream." diff --git a/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql b/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql index 73a6941612e..24fccf035b4 100644 --- a/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql +++ b/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql @@ -10,41 +10,38 @@ * maintainability * modularity */ + import csharp predicate virtualCallToSelfInConstructor(Expr e) { exists(RefType t, Virtualizable d, Callable c | - c = e.getEnclosingCallable() - and - (c instanceof Constructor or c instanceof Destructor) - and - t = c.getDeclaringType() - and - virtualAccessWithThisQualifier(e, d) - and - t.getABaseType*() = d.getDeclaringType() - and - not t.isSealed() - and + c = e.getEnclosingCallable() and + (c instanceof Constructor or c instanceof Destructor) and + t = c.getDeclaringType() and + virtualAccessWithThisQualifier(e, d) and + t.getABaseType*() = d.getDeclaringType() and + not t.isSealed() and not overriddenSealed(t.getABaseType*(), d) ) } predicate overriddenSealed(RefType t, Virtualizable d) { exists(Virtualizable od | - od.getDeclaringType() = t - and - (od.getOverridee() = d or od.getImplementee() = d) - and + od.getDeclaringType() = t and + (od.getOverridee() = d or od.getImplementee() = d) and not od.isOverridableOrImplementable() ) } predicate virtualAccessWithThisQualifier(Expr e, Member d) { - exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier()) or - exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or - exists(VirtualPropertyAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or - exists(VirtualIndexerAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or + exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier()) + or + exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) + or + exists(VirtualPropertyAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) + or + exists(VirtualIndexerAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) + or exists(VirtualEventAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) } diff --git a/csharp/ql/src/CSI/CompareIdenticalValues.ql b/csharp/ql/src/CSI/CompareIdenticalValues.ql index 66b7e54eec7..55f48d5f9a9 100644 --- a/csharp/ql/src/CSI/CompareIdenticalValues.ql +++ b/csharp/ql/src/CSI/CompareIdenticalValues.ql @@ -16,8 +16,7 @@ import semmle.code.csharp.commons.ComparisonTest import semmle.code.csharp.commons.Constants predicate isBoxingTestCase(StaticEqualsCallComparisonTest ct) { - ct.isReferenceEquals() - and + ct.isReferenceEquals() and exists(TypeParameter tp | tp = ct.getFirstArgument().stripCasts().getType() and not tp.isValueType() and @@ -25,8 +24,7 @@ predicate isBoxingTestCase(StaticEqualsCallComparisonTest ct) { ) } -predicate isMutatingOperation(Expr e) -{ +predicate isMutatingOperation(Expr e) { e.(MethodCall).getTarget().hasName("Pop") or e.(MethodCall).getTarget().hasName("Push") @@ -35,16 +33,19 @@ predicate isMutatingOperation(Expr e) } from ComparisonTest ct, Expr e, string msg -where comparesIdenticalValues(ct) - and e = ct.getExpr() - and not isBoxingTestCase(ct) - and ( - exists(string m | comparesIdenticalValuesNan(ct, m) | msg = "Comparison is equivalent to using " + m) +where + comparesIdenticalValues(ct) and + e = ct.getExpr() and + not isBoxingTestCase(ct) and + ( + exists(string m | comparesIdenticalValuesNan(ct, m) | + msg = "Comparison is equivalent to using " + m + ) or not comparesIdenticalValuesNan(ct, _) and msg = "Comparison of identical values." - ) - and not isMutatingOperation(ct.getAnArgument().getAChild*()) - and not isConstantCondition(e, _) // Avoid overlap with cs/constant-condition - and not isConstantComparison(e, _) // Avoid overlap with cs/constant-comparison - and not isExprInAssertion(e) + ) and + not isMutatingOperation(ct.getAnArgument().getAChild*()) and + not isConstantCondition(e, _) and // Avoid overlap with cs/constant-condition + not isConstantComparison(e, _) and // Avoid overlap with cs/constant-comparison + not isExprInAssertion(e) select ct, msg diff --git a/csharp/ql/src/CSI/NullMaybe.ql b/csharp/ql/src/CSI/NullMaybe.ql index 7bd099e78e9..eb20439a821 100644 --- a/csharp/ql/src/CSI/NullMaybe.ql +++ b/csharp/ql/src/CSI/NullMaybe.ql @@ -16,6 +16,7 @@ import csharp import semmle.code.csharp.dataflow.Nullness import PathGraph -from Dereference d, PathNode source, PathNode sink, Ssa::SourceVariable v, string msg, Element reason +from + Dereference d, PathNode source, PathNode sink, Ssa::SourceVariable v, string msg, Element reason where d.isFirstMaybeNull(v.getAnSsaDefinition(), source, sink, msg, reason) select d, source, sink, "Variable $@ may be null here " + msg + ".", v, v.toString(), reason, "this" diff --git a/csharp/ql/src/Complexity/BlockWithTooManyStatements.ql b/csharp/ql/src/Complexity/BlockWithTooManyStatements.ql index e03966ffe30..e472a94e6b5 100644 --- a/csharp/ql/src/Complexity/BlockWithTooManyStatements.ql +++ b/csharp/ql/src/Complexity/BlockWithTooManyStatements.ql @@ -11,14 +11,17 @@ * testability * complexity */ + import csharp class ComplexStmt extends Stmt { ComplexStmt() { - (this instanceof ForStmt or - this instanceof WhileStmt or - this instanceof DoStmt or - this instanceof SwitchStmt) + ( + this instanceof ForStmt or + this instanceof WhileStmt or + this instanceof DoStmt or + this instanceof SwitchStmt + ) } } diff --git a/csharp/ql/src/Complexity/ComplexCondition.ql b/csharp/ql/src/Complexity/ComplexCondition.ql index b9b297ba736..0c86b4f4d12 100644 --- a/csharp/ql/src/Complexity/ComplexCondition.ql +++ b/csharp/ql/src/Complexity/ComplexCondition.ql @@ -8,6 +8,7 @@ * @tags testability * readability */ + import csharp predicate nontrivialLogicalOperator(BinaryLogicalOperation e) { @@ -17,13 +18,13 @@ predicate nontrivialLogicalOperator(BinaryLogicalOperation e) { ) } -predicate logicalParent(LogicalOperation op, LogicalOperation parent) -{ - parent = op.getParent() -} +predicate logicalParent(LogicalOperation op, LogicalOperation parent) { parent = op.getParent() } from Expr e, int operators -where not (e.getParent() instanceof LogicalOperation) - and operators = count(BinaryLogicalOperation op | logicalParent*(op, e) and nontrivialLogicalOperator(op)) - and operators > 3 +where + not (e.getParent() instanceof LogicalOperation) and + operators = count(BinaryLogicalOperation op | + logicalParent*(op, e) and nontrivialLogicalOperator(op) + ) and + operators > 3 select e.getLocation(), "Complex condition: too many logical operations in this expression." diff --git a/csharp/ql/src/Concurrency/FutileSyncOnField.ql b/csharp/ql/src/Concurrency/FutileSyncOnField.ql index ce4686a497b..19b23b88a30 100755 --- a/csharp/ql/src/Concurrency/FutileSyncOnField.ql +++ b/csharp/ql/src/Concurrency/FutileSyncOnField.ql @@ -21,8 +21,10 @@ predicate lockedFieldUpdate(LockStmt lock, Field f, AssignableDefinition def) { } from LockStmt lock, Expr e, Field f, AssignableDefinition def -where e = lock.getExpr() - and f.getAnAccess() = e - and lockedFieldUpdate(lock, f, def) -select e, "Locking field $@ guards the initial value, not the value which may be seen from another thread after $@.", +where + e = lock.getExpr() and + f.getAnAccess() = e and + lockedFieldUpdate(lock, f, def) +select e, + "Locking field $@ guards the initial value, not the value which may be seen from another thread after $@.", f, f.getName(), def, "reassignment" diff --git a/csharp/ql/src/Concurrency/LockOrder.ql b/csharp/ql/src/Concurrency/LockOrder.ql index 4ab41e85fda..923f4bba2ce 100644 --- a/csharp/ql/src/Concurrency/LockOrder.ql +++ b/csharp/ql/src/Concurrency/LockOrder.ql @@ -38,7 +38,8 @@ LockStmt getAReachableLockStmt(Callable callable) { predicate nestedLocks(Variable outerVariable, Variable innerVariable, LockStmt outer, LockStmt inner) { outerVariable = outer.getLockVariable() and innerVariable = inner.getLockVariable() and - outerVariable != innerVariable and ( + outerVariable != innerVariable and + ( inner = outer.getALockedStmt() or exists(Call call | call.getEnclosingStmt() = outer.getALockedStmt() | @@ -54,9 +55,6 @@ where nestedLocks(v1, v2, outer1, inner1) and nestedLocks(v2, v1, outer2, inner2) and v1.getName() <= v2.getName() -select v1, "Inconsistent lock sequence with $@. Lock sequences $@, $@ and $@, $@ found.", - v2, v2.getName(), - outer1, v1.getName(), - inner1, v2.getName(), - outer2, v2.getName(), - inner2, v1.getName() +select v1, "Inconsistent lock sequence with $@. Lock sequences $@, $@ and $@, $@ found.", v2, + v2.getName(), outer1, v1.getName(), inner1, v2.getName(), outer2, v2.getName(), inner2, + v1.getName() diff --git a/csharp/ql/src/Concurrency/LockThis.ql b/csharp/ql/src/Concurrency/LockThis.ql index 322d2461c3c..59d08337d30 100644 --- a/csharp/ql/src/Concurrency/LockThis.ql +++ b/csharp/ql/src/Concurrency/LockThis.ql @@ -15,5 +15,5 @@ import csharp from LockStmt s, ThisAccess a -where a=s.getExpr() +where a = s.getExpr() select a, "'this' used in lock statement." diff --git a/csharp/ql/src/Concurrency/LockedWait.ql b/csharp/ql/src/Concurrency/LockedWait.ql index 9cd4026060c..584f3904ea0 100644 --- a/csharp/ql/src/Concurrency/LockedWait.ql +++ b/csharp/ql/src/Concurrency/LockedWait.ql @@ -16,10 +16,19 @@ import csharp import Concurrency from LockedBlock l, WaitStmt w, string lockedItem -where l.getALockedStmt()=w and +where + l.getALockedStmt() = w and ( - exists( Variable v | v=l.getLockVariable() and not v=w.getWaitVariable() and lockedItem=v.getName() ) or - exists( Type t | t=l.getLockTypeObject() and not t=w.getWaitTypeObject() and lockedItem = "typeof("+t.getName()+")" ) or - ( l.isLockThis() and not w.isWaitThis() and lockedItem="this" ) + exists(Variable v | + v = l.getLockVariable() and not v = w.getWaitVariable() and lockedItem = v.getName() + ) + or + exists(Type t | + t = l.getLockTypeObject() and + not t = w.getWaitTypeObject() and + lockedItem = "typeof(" + t.getName() + ")" + ) + or + (l.isLockThis() and not w.isWaitThis() and lockedItem = "this") ) select w, "'" + lockedItem + "' is locked during this wait." diff --git a/csharp/ql/src/Concurrency/SynchSetUnsynchGet.ql b/csharp/ql/src/Concurrency/SynchSetUnsynchGet.ql index 7b1761a921e..f2f216d2f88 100644 --- a/csharp/ql/src/Concurrency/SynchSetUnsynchGet.ql +++ b/csharp/ql/src/Concurrency/SynchSetUnsynchGet.ql @@ -15,26 +15,17 @@ import csharp from Property p, Field f where - f.getDeclaringType() = p.getDeclaringType() - and + f.getDeclaringType() = p.getDeclaringType() and exists(Setter setter, LockStmt writelock, FieldWrite writeaccess | - p.getSetter() = setter - and - writeaccess = f.getAnAccess() - and - writelock.getEnclosingCallable() = setter - and + p.getSetter() = setter and + writeaccess = f.getAnAccess() and + writelock.getEnclosingCallable() = setter and writelock.getAChildStmt+().getAChildExpr+() = writeaccess - ) - and + ) and exists(Getter getter, FieldRead readaccess | - getter = p.getGetter() - and - readaccess = f.getAnAccess() - and - readaccess.getEnclosingCallable() = getter - and - not exists(LockStmt readlock | - readlock.getAChildStmt+().getAChildExpr+() = readaccess) - ) + getter = p.getGetter() and + readaccess = f.getAnAccess() and + readaccess.getEnclosingCallable() = getter and + not exists(LockStmt readlock | readlock.getAChildStmt+().getAChildExpr+() = readaccess) + ) select p, "Field '$@' is guarded by a lock in the setter but not in the getter.", f, f.getName() diff --git a/csharp/ql/src/Concurrency/UnsafeLazyInitialization.ql b/csharp/ql/src/Concurrency/UnsafeLazyInitialization.ql index 278eabe1b72..f67defc9732 100644 --- a/csharp/ql/src/Concurrency/UnsafeLazyInitialization.ql +++ b/csharp/ql/src/Concurrency/UnsafeLazyInitialization.ql @@ -15,7 +15,7 @@ import csharp import semmle.code.csharp.commons.StructuralComparison class DoubleCheckedLock extends StructuralComparisonConfiguration { - DoubleCheckedLock() { this="double checked lock" } + DoubleCheckedLock() { this = "double checked lock" } override predicate candidate(Element x, Element y) { exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock | @@ -28,8 +28,7 @@ class DoubleCheckedLock extends StructuralComparisonConfiguration { } predicate doubleCheckedLock(Field field, IfStmt ifs) { - exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 | - ifs.getCondition() = eq1 | + exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 | ifs.getCondition() = eq1 | lock = ifs.getThen().stripSingletonBlocks() and config.same(eq1, eq2) and field.getAnAccess() = eq1.getAChildExpr*() @@ -37,9 +36,7 @@ predicate doubleCheckedLock(Field field, IfStmt ifs) { } from Field field, IfStmt ifs -where doubleCheckedLock(field, ifs) -and not field.isVolatile() -select ifs, "Field $@ should be 'volatile' for this double-checked lock.", - field, field.getName() - - +where + doubleCheckedLock(field, ifs) and + not field.isVolatile() +select ifs, "Field $@ should be 'volatile' for this double-checked lock.", field, field.getName() diff --git a/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.ql b/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.ql index 724bad88c64..650cf9a1f0c 100644 --- a/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.ql +++ b/csharp/ql/src/Concurrency/UnsynchronizedStaticAccess.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-362 * external/cwe/cwe-567 */ + import csharp import DataMembers import ThreadCreation @@ -24,7 +25,8 @@ predicate correctlySynchronized(CollectionMember c, Expr access) { } ControlFlow::Node unlockedReachable(Callable a) { - result = a.getEntryPoint() or + result = a.getEntryPoint() + or exists(ControlFlow::Node mid | mid = unlockedReachable(a) | not mid.getElement() instanceof LockingCall and result = mid.getASuccessor() @@ -40,22 +42,22 @@ predicate unlockedCalls(Callable a, Callable b) { } predicate writtenStaticDictionary(CollectionMember c) { - c.getType().(ValueOrRefType).getABaseType*().hasName("IDictionary") - and c.isStatic() - and exists(Expr write | write = c.getAWrite() | + c.getType().(ValueOrRefType).getABaseType*().hasName("IDictionary") and + c.isStatic() and + exists(Expr write | write = c.getAWrite() | not write.getEnclosingCallable() instanceof StaticConstructor ) } -predicate nonStaticCallable(Callable c) { - not c.(Modifiable).isStatic() -} +predicate nonStaticCallable(Callable c) { not c.(Modifiable).isStatic() } -from CollectionMember c, Expr a, ConcurrentEntryPoint e,Callable enclosing -where a = c.getAReadOrWrite() - and enclosing = a.getEnclosingCallable() - and nonStaticCallable(enclosing) - and not correctlySynchronized(c, a) - and unlockedCalls*(e, enclosing) - and writtenStaticDictionary(c) -select a, "Unsynchronized access to $@ in non-static context from $@.", c, c.getName(), e, e.getName() +from CollectionMember c, Expr a, ConcurrentEntryPoint e, Callable enclosing +where + a = c.getAReadOrWrite() and + enclosing = a.getEnclosingCallable() and + nonStaticCallable(enclosing) and + not correctlySynchronized(c, a) and + unlockedCalls*(e, enclosing) and + writtenStaticDictionary(c) +select a, "Unsynchronized access to $@ in non-static context from $@.", c, c.getName(), e, + e.getName() diff --git a/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql b/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql index 93aa77351cd..315e5e084bd 100644 --- a/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql +++ b/csharp/ql/src/Configuration/EmptyPasswordInConfigurationFile.ql @@ -9,10 +9,14 @@ * external/cwe/cwe-258 * external/cwe/cwe-862 */ + import csharp from XMLAttribute a -where a.getName().toLowerCase() = "password" and a.getValue() = "" - or a.getName().toLowerCase() = "pwd" and a.getValue() = "" - or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=\\s*;.*") +where + a.getName().toLowerCase() = "password" and a.getValue() = "" + or + a.getName().toLowerCase() = "pwd" and a.getValue() = "" + or + a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=\\s*;.*") select a, "Do not use empty passwords." diff --git a/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql b/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql index 2dacd2da752..85c332345d6 100644 --- a/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql +++ b/csharp/ql/src/Configuration/PasswordInConfigurationFile.ql @@ -10,10 +10,14 @@ * external/cwe/cwe-256 * external/cwe/cwe-313 */ + import csharp from XMLAttribute a -where a.getName().toLowerCase() = "password" and not a.getValue() = "" - or a.getName().toLowerCase() = "pwd" and not a.getValue() = "" - or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") +where + a.getName().toLowerCase() = "password" and not a.getValue() = "" + or + a.getName().toLowerCase() = "pwd" and not a.getValue() = "" + or + a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") select a, "Avoid plaintext passwords in configuration files." diff --git a/csharp/ql/src/Dead Code/DeadRefTypes.ql b/csharp/ql/src/Dead Code/DeadRefTypes.ql index 1db186fc178..6790de5416f 100644 --- a/csharp/ql/src/Dead Code/DeadRefTypes.ql +++ b/csharp/ql/src/Dead Code/DeadRefTypes.ql @@ -9,45 +9,43 @@ * useless-code * external/cwe/cwe-561 */ + import csharp import semmle.code.csharp.commons.Util import semmle.code.csharp.frameworks.Test import semmle.code.csharp.metrics.Coupling -predicate potentiallyUsedFromXaml(RefType t) -{ +predicate potentiallyUsedFromXaml(RefType t) { exists(string name | name = t.getABaseType*().getQualifiedName() | - name = "System.Windows.Data.IValueConverter" - or name = "System.Windows.Data.IMultiValueConverter" + name = "System.Windows.Data.IValueConverter" or + name = "System.Windows.Data.IMultiValueConverter" ) } -class ExportAttribute extends Attribute -{ - ExportAttribute() - { +class ExportAttribute extends Attribute { + ExportAttribute() { getType().hasQualifiedName("System.ComponentModel.Composition.ExportAttribute") } } from RefType t where - not extractionIsStandalone() - and t.fromSource() - and t = t.getSourceDeclaration() - and not t instanceof AnonymousClass - and not (t.isPublic() or t.isProtected()) - and not exists (ValueOrRefType dependent | depends(dependent, t) and dependent != t) - and not exists (ConstructedType ct | usesType(ct, t)) - and not exists (MethodCall call | usesType(call.getTarget().(ConstructedMethod).getATypeArgument(), t)) - and not t.getAMethod() instanceof MainMethod - and not potentiallyUsedFromXaml(t) - and not exists(TypeofExpr typeof | typeof.getTypeAccess().getTarget() = t) - and not t instanceof TestClass + not extractionIsStandalone() and + t.fromSource() and + t = t.getSourceDeclaration() and + not t instanceof AnonymousClass and + not (t.isPublic() or t.isProtected()) and + not exists(ValueOrRefType dependent | depends(dependent, t) and dependent != t) and + not exists(ConstructedType ct | usesType(ct, t)) and + not exists(MethodCall call | usesType(call.getTarget().(ConstructedMethod).getATypeArgument(), t)) and + not t.getAMethod() instanceof MainMethod and + not potentiallyUsedFromXaml(t) and + not exists(TypeofExpr typeof | typeof.getTypeAccess().getTarget() = t) and + not t instanceof TestClass and // MemberConstant nodes are compile-time constant and can appear in various contexts // where they don't have enclosing callables or types (e.g. in attribute values). // Classes that are declared purely to hold member constants which are used are, // therefore, not dead. - and not exists(t.getAMember().(MemberConstant).getAnAccess()) - and not t.getAnAttribute() instanceof ExportAttribute + not exists(t.getAMember().(MemberConstant).getAnAccess()) and + not t.getAnAttribute() instanceof ExportAttribute select t, "Unused reference type " + t + "." diff --git a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql index e232b0f0a34..99c739095c4 100644 --- a/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql +++ b/csharp/ql/src/Dead Code/DeadStoreOfLocal.ql @@ -20,8 +20,7 @@ import csharp Callable getACapturingCallableAncestor(LocalVariable v) { result = v.getACapturingCallable() or - exists(Callable mid | - mid = getACapturingCallableAncestor(v) | + exists(Callable mid | mid = getACapturingCallableAncestor(v) | result = mid.getEnclosingCallable() and not v.getEnclosingCallable() = result ) @@ -37,8 +36,7 @@ Expr getADelegateExpr(Callable c) { * Holds if `c` is a call where any delegate argument is evaluated immediately. */ predicate nonEscapingCall(Call c) { - exists(string name | - c.getTarget().hasName(name) | + exists(string name | c.getTarget().hasName(name) | name = "ForEach" or name = "Count" or name = "Any" or @@ -62,8 +60,7 @@ predicate nonEscapingCall(Call c) { * `v` may escape the local scope. */ predicate mayEscape(LocalVariable v) { - exists(Callable c, Expr e, Expr succ | - c = getACapturingCallableAncestor(v) | + exists(Callable c, Expr e, Expr succ | c = getACapturingCallableAncestor(v) | e = getADelegateExpr(c) and DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(succ)) and not succ = any(DelegateCall dc).getDelegateExpr() and @@ -80,15 +77,15 @@ class RelevantDefinition extends AssignableDefinition { this instanceof AssignableDefinitions::MutationDefinition or this instanceof AssignableDefinitions::TupleAssignmentDefinition + or // Discards in out assignments are only possible from C# 7 (2017), so we disable this case // for now //or //this.(AssignableDefinitions::OutRefDefinition).getTargetAccess().isOutArgument() - or this.(AssignableDefinitions::LocalVariableDefinition).getDeclaration() = any(LocalVariableDeclExpr lvde | - lvde = any(SpecificCatchClause scc).getVariableDeclExpr() or - lvde = any(ForeachStmt fs).getVariableDeclExpr() - ) + lvde = any(SpecificCatchClause scc).getVariableDeclExpr() or + lvde = any(ForeachStmt fs).getVariableDeclExpr() + ) or this instanceof AssignableDefinitions::IsPatternDefinition or @@ -97,8 +94,7 @@ class RelevantDefinition extends AssignableDefinition { /** Holds if this assignment may be live. */ private predicate isMaybeLive() { - exists(LocalVariable v | - v = this.getTarget() | + exists(LocalVariable v | v = this.getTarget() | // SSA definitions are only created for live variables this = any(Ssa::ExplicitDefinition ssaDef).getADefinition() or @@ -117,10 +113,8 @@ class RelevantDefinition extends AssignableDefinition { */ private predicate isDefaultLikeInitializer() { this.isInitializer() and - exists(Expr e | - e = this.getSource() | - exists(string val | - val = e.getValue() | + exists(Expr e | e = this.getSource() | + exists(string val | val = e.getValue() | val = "0" or val = "-1" or val = "" or @@ -129,7 +123,10 @@ class RelevantDefinition extends AssignableDefinition { or e instanceof NullLiteral or - e = any(Field f | f.isStatic() and (f.isReadOnly() or f.isConst())).getAnAccess() + e = any(Field f | + f.isStatic() and + (f.isReadOnly() or f.isConst()) + ).getAnAccess() or e instanceof DefaultValueExpr or @@ -151,8 +148,7 @@ class RelevantDefinition extends AssignableDefinition { ( not this.isDefaultLikeInitializer() or - not exists(AssignableDefinition other | - other.getTarget() = this.getTarget() | + not exists(AssignableDefinition other | other.getTarget() = this.getTarget() | other != this ) ) @@ -161,6 +157,7 @@ class RelevantDefinition extends AssignableDefinition { } from RelevantDefinition def, LocalVariable v -where v = def.getTarget() - and def.isDead() +where + v = def.getTarget() and + def.isDead() select def, "This assignment to $@ is useless, since its value is never read.", v, v.getName() diff --git a/csharp/ql/src/Dead Code/NonAssignedFields.ql b/csharp/ql/src/Dead Code/NonAssignedFields.ql index 0817f8de204..c3254c2c0d0 100644 --- a/csharp/ql/src/Dead Code/NonAssignedFields.ql +++ b/csharp/ql/src/Dead Code/NonAssignedFields.ql @@ -16,108 +16,102 @@ import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.runtime.InteropServices // Any field transitively contained in t. -Field getANestedField(ValueOrRefType t) -{ +Field getANestedField(ValueOrRefType t) { result.getDeclaringType() = t or exists(Field mid | - mid=getANestedField(t) - and - mid.getType() = result.getDeclaringType()) + mid = getANestedField(t) and + mid.getType() = result.getDeclaringType() + ) } // Any ValueOrRefType referenced by a Type, including TypeParameters. -ValueOrRefType getAReferencedType(Type t) -{ +ValueOrRefType getAReferencedType(Type t) { result = t or result = t.(TypeParameter).getASuppliedType() } -predicate isTypeExternallyInitialized(ValueOrRefType t) -{ +predicate isTypeExternallyInitialized(ValueOrRefType t) { // The type got created via a call to PtrToStructure(). exists(MethodCall mc | - mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod() - and + mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod() and t = getAReferencedType(mc.getArgument(1).(TypeofExpr).getTypeAccess().getTarget()) - ) - + ) + or // The type got created via a call to PtrToStructure(). - or exists(MethodCall mc | - mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod() - and + exists(MethodCall mc | + mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod() and t = getAReferencedType(mc.getArgument(1).getType()) - ) - + ) + or // An extern method exists which could initialize the type. - or exists(Method m, Parameter p | + exists(Method m, Parameter p | isExternMethod(m) and - p=m.getAParameter() and + p = m.getAParameter() and t = p.getType() - | - p.isOut() or p.isRef()) - + | + p.isOut() or p.isRef() + ) + or // The data structure has been cast to a pointer - all bets are off. - or exists(CastExpr c | - t = getAReferencedType(c.getTargetType().(PointerType).getReferentType())) + exists(CastExpr c | t = getAReferencedType(c.getTargetType().(PointerType).getReferentType())) } // The type is potentially marshaled using an extern or interop. -predicate isFieldExternallyInitialized(Field f) -{ +predicate isFieldExternallyInitialized(Field f) { exists(ValueOrRefType t | - f = getANestedField(t) - and - isTypeExternallyInitialized(t)) + f = getANestedField(t) and + isTypeExternallyInitialized(t) + ) } -predicate isExternMethod(Method externMethod) -{ +predicate isExternMethod(Method externMethod) { externMethod.isExtern() or - externMethod.getAnAttribute().getType() instanceof SystemRuntimeInteropServicesDllImportAttributeClass + externMethod.getAnAttribute().getType() instanceof + SystemRuntimeInteropServicesDllImportAttributeClass or - externMethod.getDeclaringType().getAnAttribute().getType() instanceof SystemRuntimeInteropServicesComImportAttributeClass + externMethod.getDeclaringType().getAnAttribute().getType() instanceof + SystemRuntimeInteropServicesComImportAttributeClass } from Field f, FieldRead fa where - f.fromSource() - and not extractionIsStandalone() - and not f.isReadOnly() - and not f.isConst() - and not f.getDeclaringType() instanceof Enum - and not f.getType() instanceof Struct - and not exists(Assignment ae, Field g | - ae.getLValue().(FieldAccess).getTarget() = g - and g.getSourceDeclaration() = f - and not (ae.getRValue() instanceof NullLiteral) - ) - and not exists(MethodCall mc, int i, Field g | - exists(Parameter p | mc.getTarget().getParameter(i) = p | - p.isOut() or p.isRef() - ) - and mc.getArgument(i) = g.getAnAccess() - and g.getSourceDeclaration() = f - ) - and not isFieldExternallyInitialized(f) - and not exists(f.getAnAttribute()) - and not exists(Expr init, Field g | + f.fromSource() and + not extractionIsStandalone() and + not f.isReadOnly() and + not f.isConst() and + not f.getDeclaringType() instanceof Enum and + not f.getType() instanceof Struct and + not exists(Assignment ae, Field g | + ae.getLValue().(FieldAccess).getTarget() = g and + g.getSourceDeclaration() = f and + not (ae.getRValue() instanceof NullLiteral) + ) and + not exists(MethodCall mc, int i, Field g | + exists(Parameter p | mc.getTarget().getParameter(i) = p | p.isOut() or p.isRef()) and + mc.getArgument(i) = g.getAnAccess() and g.getSourceDeclaration() = f - and g.getInitializer() = init - and not init instanceof NullLiteral - ) - and not exists(AssignOperation ua, Field g | - ua.getLValue().(FieldAccess).getTarget() = g - and g.getSourceDeclaration() = f - ) - and not exists(MutatorOperation op | + ) and + not isFieldExternallyInitialized(f) and + not exists(f.getAnAttribute()) and + not exists(Expr init, Field g | + g.getSourceDeclaration() = f and + g.getInitializer() = init and + not init instanceof NullLiteral + ) and + not exists(AssignOperation ua, Field g | + ua.getLValue().(FieldAccess).getTarget() = g and + g.getSourceDeclaration() = f + ) and + not exists(MutatorOperation op | op.getAnOperand().(FieldAccess).getTarget().getSourceDeclaration() = f + ) and + exists(Field g | + fa.getTarget() = g and + g.getSourceDeclaration() = f ) - and exists(Field g | - fa.getTarget() = g - and g.getSourceDeclaration() = f - ) -select f, "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.", - fa, "here" +select f, + "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.", fa, + "here" diff --git a/csharp/ql/src/Dead Code/UnusedField.ql b/csharp/ql/src/Dead Code/UnusedField.ql index 5d2537b8818..435ec6a370c 100644 --- a/csharp/ql/src/Dead Code/UnusedField.ql +++ b/csharp/ql/src/Dead Code/UnusedField.ql @@ -9,13 +9,14 @@ * useless-code * external/cwe/cwe-561 */ + import csharp import DeadCode from Field f where - not extractionIsStandalone() - and f.fromSource() - and isDeadField(f) - and not f.getDeclaringType().isPartial() + not extractionIsStandalone() and + f.fromSource() and + isDeadField(f) and + not f.getDeclaringType().isPartial() select f, "Unused field (or field used from dead method only)" diff --git a/csharp/ql/src/Dead Code/UnusedMethod.ql b/csharp/ql/src/Dead Code/UnusedMethod.ql index c936deac51f..628803281f4 100644 --- a/csharp/ql/src/Dead Code/UnusedMethod.ql +++ b/csharp/ql/src/Dead Code/UnusedMethod.ql @@ -10,13 +10,14 @@ * useless-code * external/cwe/cwe-561 */ + import csharp import DeadCode from Method m where - not extractionIsStandalone() - and m.fromSource() - and isDeadMethod(m) - and not m.getDeclaringType().isPartial() + not extractionIsStandalone() and + m.fromSource() and + isDeadMethod(m) and + not m.getDeclaringType().isPartial() select m, "Unused method (or method called from dead method only)" diff --git a/csharp/ql/src/Documentation/XmldocExtraParam.ql b/csharp/ql/src/Documentation/XmldocExtraParam.ql index 3a25dba77a0..be42720d439 100644 --- a/csharp/ql/src/Documentation/XmldocExtraParam.ql +++ b/csharp/ql/src/Documentation/XmldocExtraParam.ql @@ -12,7 +12,8 @@ import Documentation from SourceMethodOrConstructor m, ParamXmlComment comment, string paramName -where comment = getADeclarationXmlComment(m) -and comment.getName(_)=paramName -and not m.getAParameter().getName() = paramName +where + comment = getADeclarationXmlComment(m) and + comment.getName(_) = paramName and + not m.getAParameter().getName() = paramName select m, "Documentation specifies an invalid parameter name $@.", comment, paramName diff --git a/csharp/ql/src/Documentation/XmldocExtraTypeParam.ql b/csharp/ql/src/Documentation/XmldocExtraTypeParam.ql index e2afd9295d1..4763b3d958c 100644 --- a/csharp/ql/src/Documentation/XmldocExtraTypeParam.ql +++ b/csharp/ql/src/Documentation/XmldocExtraTypeParam.ql @@ -12,7 +12,8 @@ import Documentation from UnboundGeneric d, TypeparamXmlComment comment, string paramName -where comment = getADeclarationXmlComment(d) -and comment.getName(_) = paramName -and not d.getATypeParameter().getName() = paramName +where + comment = getADeclarationXmlComment(d) and + comment.getName(_) = paramName and + not d.getATypeParameter().getName() = paramName select d, "Documentation specifies an invalid type parameter name $@.", comment, paramName diff --git a/csharp/ql/src/Documentation/XmldocMissing.ql b/csharp/ql/src/Documentation/XmldocMissing.ql index 50f8152a88e..e0e05c4893b 100644 --- a/csharp/ql/src/Documentation/XmldocMissing.ql +++ b/csharp/ql/src/Documentation/XmldocMissing.ql @@ -12,16 +12,20 @@ import Documentation /** Generate a user-friendly string for the declaration */ -string declarationDescription(Declaration d) -{ - d instanceof Class and result="class" or - d instanceof Interface and result="interface" or - d instanceof Method and result="method" or - d instanceof Constructor and result="constructor" or - d instanceof Struct and result="struct" +string declarationDescription(Declaration d) { + d instanceof Class and result = "class" + or + d instanceof Interface and result = "interface" + or + d instanceof Method and result = "method" + or + d instanceof Constructor and result = "constructor" + or + d instanceof Struct and result = "struct" } from Declaration decl -where isDocumentationNeeded(decl) -and not declarationHasXmlComment(decl) +where + isDocumentationNeeded(decl) and + not declarationHasXmlComment(decl) select decl, "Public " + declarationDescription(decl) + " should be documented." diff --git a/csharp/ql/src/Documentation/XmldocMissingException.ql b/csharp/ql/src/Documentation/XmldocMissingException.ql index ad8edda66f9..87af9c299f5 100644 --- a/csharp/ql/src/Documentation/XmldocMissingException.ql +++ b/csharp/ql/src/Documentation/XmldocMissingException.ql @@ -12,15 +12,16 @@ import Documentation from SourceMethodOrConstructor m, ThrowElement throw, RefType throwType -where declarationHasXmlComment(m) -and m = throw.getEnclosingCallable() -and throwType = throw.getExpr().getType() -and not exists(ExceptionXmlComment comment, int offset, string exceptionName, RefType throwBaseType | - comment = getADeclarationXmlComment(m) - and exceptionName = comment.getCref(offset) - and throwType.getABaseType*() = throwBaseType - and (throwBaseType.hasName(exceptionName) or throwBaseType.hasQualifiedName(exceptionName)) +where + declarationHasXmlComment(m) and + m = throw.getEnclosingCallable() and + throwType = throw.getExpr().getType() and + not exists(ExceptionXmlComment comment, int offset, string exceptionName, RefType throwBaseType | + comment = getADeclarationXmlComment(m) and + exceptionName = comment.getCref(offset) and + throwType.getABaseType*() = throwBaseType and + (throwBaseType.hasName(exceptionName) or throwBaseType.hasQualifiedName(exceptionName)) // and comment.hasBody(offset) // Too slow - ) -and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment + ) and + not getADeclarationXmlComment(m) instanceof InheritDocXmlComment select m, "Exception $@ should be documented.", throw, throw.getExpr().getType().getName() diff --git a/csharp/ql/src/Documentation/XmldocMissingParam.ql b/csharp/ql/src/Documentation/XmldocMissingParam.ql index d071641920f..1926bee4eb6 100644 --- a/csharp/ql/src/Documentation/XmldocMissingParam.ql +++ b/csharp/ql/src/Documentation/XmldocMissingParam.ql @@ -12,11 +12,13 @@ import Documentation from SourceMethodOrConstructor m, SourceParameter p -where p = m.getAParameter() -and declarationHasXmlComment(m) -and not exists( ParamXmlComment c, int offset | - c = getADeclarationXmlComment(m) - and c.getName(offset) = p.getName() - and c.hasBody(offset) ) -and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment +where + p = m.getAParameter() and + declarationHasXmlComment(m) and + not exists(ParamXmlComment c, int offset | + c = getADeclarationXmlComment(m) and + c.getName(offset) = p.getName() and + c.hasBody(offset) + ) and + not getADeclarationXmlComment(m) instanceof InheritDocXmlComment select p, "Parameter should be documented." diff --git a/csharp/ql/src/Documentation/XmldocMissingReturn.ql b/csharp/ql/src/Documentation/XmldocMissingReturn.ql index f8249b695f7..112c6238d97 100644 --- a/csharp/ql/src/Documentation/XmldocMissingReturn.ql +++ b/csharp/ql/src/Documentation/XmldocMissingReturn.ql @@ -12,9 +12,11 @@ import Documentation from SourceMethod m -where declarationHasXmlComment(m) -and forall(ReturnsXmlComment c | c=getADeclarationXmlComment(m) | - forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset) ) ) -and not m.getReturnType() instanceof VoidType -and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment +where + declarationHasXmlComment(m) and + forall(ReturnsXmlComment c | c = getADeclarationXmlComment(m) | + forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset)) + ) and + not m.getReturnType() instanceof VoidType and + not getADeclarationXmlComment(m) instanceof InheritDocXmlComment select m, "Return value should be documented." diff --git a/csharp/ql/src/Documentation/XmldocMissingSummary.ql b/csharp/ql/src/Documentation/XmldocMissingSummary.ql index 636a2a8469d..74238b63ed4 100644 --- a/csharp/ql/src/Documentation/XmldocMissingSummary.ql +++ b/csharp/ql/src/Documentation/XmldocMissingSummary.ql @@ -11,9 +11,11 @@ import Documentation from Declaration decl -where declarationHasXmlComment(decl) -and isDocumentationNeeded(decl) -and forall(SummaryXmlComment c | c=getADeclarationXmlComment(decl) | - forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset) ) ) -and not getADeclarationXmlComment(decl) instanceof InheritDocXmlComment +where + declarationHasXmlComment(decl) and + isDocumentationNeeded(decl) and + forall(SummaryXmlComment c | c = getADeclarationXmlComment(decl) | + forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset)) + ) and + not getADeclarationXmlComment(decl) instanceof InheritDocXmlComment select decl, "Documentation should have a summary." diff --git a/csharp/ql/src/Documentation/XmldocMissingTypeParam.ql b/csharp/ql/src/Documentation/XmldocMissingTypeParam.ql index 7b47bc3a1d1..d559783146c 100644 --- a/csharp/ql/src/Documentation/XmldocMissingTypeParam.ql +++ b/csharp/ql/src/Documentation/XmldocMissingTypeParam.ql @@ -12,11 +12,13 @@ import Documentation from UnboundGeneric d, TypeParameter p -where p=d.getATypeParameter() -and declarationHasXmlComment(d) -and not exists(TypeparamXmlComment comment, int offset | - comment = getADeclarationXmlComment(d) - and comment.getName(offset) = p.getName() - and comment.hasBody(offset) ) -and not getADeclarationXmlComment(d) instanceof InheritDocXmlComment +where + p = d.getATypeParameter() and + declarationHasXmlComment(d) and + not exists(TypeparamXmlComment comment, int offset | + comment = getADeclarationXmlComment(d) and + comment.getName(offset) = p.getName() and + comment.hasBody(offset) + ) and + not getADeclarationXmlComment(d) instanceof InheritDocXmlComment select p, "Type parameter should be documented." diff --git a/csharp/ql/src/Input Validation/UseOfFileUpload.ql b/csharp/ql/src/Input Validation/UseOfFileUpload.ql index 04d06c2658b..f3a3b0aeffa 100644 --- a/csharp/ql/src/Input Validation/UseOfFileUpload.ql +++ b/csharp/ql/src/Input Validation/UseOfFileUpload.ql @@ -10,9 +10,11 @@ * frameworks/asp.net * external/cwe/cwe-434 */ + import csharp from PropertyAccess pa -where pa.getTarget().hasName("PostedFile") - and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.UI.HtmlControls", "HtmlInputFile") +where + pa.getTarget().hasName("PostedFile") and + pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.UI.HtmlControls", "HtmlInputFile") select pa, "Avoid using file upload." diff --git a/csharp/ql/src/Input Validation/ValueShadowing.ql b/csharp/ql/src/Input Validation/ValueShadowing.ql index b4c45af0407..26d4f6cfa16 100644 --- a/csharp/ql/src/Input Validation/ValueShadowing.ql +++ b/csharp/ql/src/Input Validation/ValueShadowing.ql @@ -9,10 +9,12 @@ * maintainability * frameworks/asp.net */ + import csharp import semmle.code.csharp.frameworks.system.web.Http from IndexerAccess ia -where ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") - and not isServerVariable(ia.getIndex(0)) +where + ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") and + not isServerVariable(ia.getIndex(0)) select ia, "Ambiguous access to variable." diff --git a/csharp/ql/src/Input Validation/ValueShadowingServerVariable.ql b/csharp/ql/src/Input Validation/ValueShadowingServerVariable.ql index aa1876132b1..e25259f2292 100644 --- a/csharp/ql/src/Input Validation/ValueShadowingServerVariable.ql +++ b/csharp/ql/src/Input Validation/ValueShadowingServerVariable.ql @@ -9,10 +9,12 @@ * maintainability * frameworks/asp.net */ + import csharp import semmle.code.csharp.frameworks.system.web.Http from IndexerAccess ia -where ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") - and isServerVariable(ia.getIndex(0)) +where + ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") and + isServerVariable(ia.getIndex(0)) select ia, "Ambiguous access to server variable." diff --git a/csharp/ql/src/Language Abuse/CastThisToTypeParameter.ql b/csharp/ql/src/Language Abuse/CastThisToTypeParameter.ql index bcb938e80b5..0842845ed27 100644 --- a/csharp/ql/src/Language Abuse/CastThisToTypeParameter.ql +++ b/csharp/ql/src/Language Abuse/CastThisToTypeParameter.ql @@ -13,10 +13,11 @@ import csharp from ExplicitCast c, ConstructedType src, TypeParameter dest -where c.getExpr() instanceof ThisAccess - and src = c.getExpr().getType() - and dest = c.getTargetType() - and dest = src.getUnboundGeneric().getATypeParameter() -select c, "Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.", - dest, dest.getName(), - src, src.getName() +where + c.getExpr() instanceof ThisAccess and + src = c.getExpr().getType() and + dest = c.getTargetType() and + dest = src.getUnboundGeneric().getATypeParameter() +select c, + "Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.", + dest, dest.getName(), src, src.getName() diff --git a/csharp/ql/src/Language Abuse/CatchOfGenericException.ql b/csharp/ql/src/Language Abuse/CatchOfGenericException.ql index e85654bccf6..90f8c87cde5 100644 --- a/csharp/ql/src/Language Abuse/CatchOfGenericException.ql +++ b/csharp/ql/src/Language Abuse/CatchOfGenericException.ql @@ -19,16 +19,18 @@ class GenericCatchClause extends CatchClause { this instanceof GeneralCatchClause or this = any(SpecificCatchClause scc | - scc.getCaughtExceptionType() instanceof SystemExceptionClass and - not scc.hasFilterClause() - ) + scc.getCaughtExceptionType() instanceof SystemExceptionClass and + not scc.hasFilterClause() + ) } } from GenericCatchClause gcc -where forall(ThrowStmt throw | - // ok to catch all exceptions if they may be rethrown - gcc.getBlock().getAChildStmt+() = throw | - exists(throw.getExpr()) -) +where + forall(ThrowStmt throw | + // ok to catch all exceptions if they may be rethrown + gcc.getBlock().getAChildStmt+() = throw + | + exists(throw.getExpr()) + ) select gcc, "Generic catch clause." diff --git a/csharp/ql/src/Language Abuse/ChainedIs.ql b/csharp/ql/src/Language Abuse/ChainedIs.ql index 95ff74f1378..ed2fb3c68de 100644 --- a/csharp/ql/src/Language Abuse/ChainedIs.ql +++ b/csharp/ql/src/Language Abuse/ChainedIs.ql @@ -15,25 +15,20 @@ import csharp int isCountForIfChain(IfStmt is) { exists(int rest | + (if is.getElse() instanceof IfStmt then rest = isCountForIfChain(is.getElse()) else rest = 0) and ( - if is.getElse() instanceof IfStmt then - rest = isCountForIfChain(is.getElse()) - else - rest = 0 - ) - and - ( - if is.getCondition().(IsTypeExpr).getCheckedType().getSourceDeclaration().fromSource() then - result = 1 + rest - else - result = rest + if is.getCondition().(IsTypeExpr).getCheckedType().getSourceDeclaration().fromSource() + then result = 1 + rest + else result = rest ) ) } from IfStmt is, int n where - n = isCountForIfChain(is) - and n > 5 - and not exists(IfStmt other | is = other.getElse()) -select is, "This if block performs a chain of " + n + " type tests - consider alternatives, e.g. polymorphism or the visitor pattern." + n = isCountForIfChain(is) and + n > 5 and + not exists(IfStmt other | is = other.getElse()) +select is, + "This if block performs a chain of " + n + + " type tests - consider alternatives, e.g. polymorphism or the visitor pattern." diff --git a/csharp/ql/src/Language Abuse/DubiousDowncastOfThis.ql b/csharp/ql/src/Language Abuse/DubiousDowncastOfThis.ql index 4a7698df654..4082a2b3ce8 100644 --- a/csharp/ql/src/Language Abuse/DubiousDowncastOfThis.ql +++ b/csharp/ql/src/Language Abuse/DubiousDowncastOfThis.ql @@ -13,10 +13,10 @@ import csharp from ExplicitCast c, ValueOrRefType src, ValueOrRefType dest -where c.getExpr() instanceof ThisAccess - and src = c.getExpr().getType() - and dest = c.getTargetType() - and src = dest.getABaseType+() +where + c.getExpr() instanceof ThisAccess and + src = c.getExpr().getType() and + dest = c.getTargetType() and + src = dest.getABaseType+() select c, "Downcasting 'this' from $@ to $@ introduces a dependency cycle between the two types.", - src, src.getName(), - dest, dest.getName() + src, src.getName(), dest, dest.getName() diff --git a/csharp/ql/src/Language Abuse/DubiousTypeTestOfThis.ql b/csharp/ql/src/Language Abuse/DubiousTypeTestOfThis.ql index 34780fa1211..840793fbd34 100644 --- a/csharp/ql/src/Language Abuse/DubiousTypeTestOfThis.ql +++ b/csharp/ql/src/Language Abuse/DubiousTypeTestOfThis.ql @@ -15,11 +15,11 @@ import semmle.code.csharp.commons.Assertions from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct where - ise.getExpr() instanceof ThisAccess - and t = ise.getExpr().getType() - and ct = ise.getCheckedType() - and ct.getABaseType*() = t - and not isExprInAssertion(ise) -select ise, "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.", - ct, ct.getName(), - t, t.getName() + ise.getExpr() instanceof ThisAccess and + t = ise.getExpr().getType() and + ct = ise.getCheckedType() and + ct.getABaseType*() = t and + not isExprInAssertion(ise) +select ise, + "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.", + ct, ct.getName(), t, t.getName() diff --git a/csharp/ql/src/Language Abuse/ForeachCapture.ql b/csharp/ql/src/Language Abuse/ForeachCapture.ql index 7519ecd5b31..f252e6294e7 100644 --- a/csharp/ql/src/Language Abuse/ForeachCapture.ql +++ b/csharp/ql/src/Language Abuse/ForeachCapture.ql @@ -17,10 +17,7 @@ import semmle.code.csharp.frameworks.system.Collections import semmle.code.csharp.frameworks.system.collections.Generic predicate lambdaCaptures(AnonymousFunctionExpr lambda, Variable v) { - exists(VariableAccess va | - va.getEnclosingCallable() = lambda | - va.getTarget() = v - ) + exists(VariableAccess va | va.getEnclosingCallable() = lambda | va.getTarget() = v) } predicate lambdaCapturesLoopVariable(AnonymousFunctionExpr lambda, ForeachStmt loop, Variable v) { @@ -33,41 +30,34 @@ predicate inForeachStmtBody(ForeachStmt loop, Element e) { e = loop.getBody() or exists(Element mid | - inForeachStmtBody(loop, mid) - and + inForeachStmtBody(loop, mid) and e = mid.getAChild() ) } class LambdaDataFlowConfiguration extends DataFlow::Configuration { - LambdaDataFlowConfiguration() { - this = "LambdaDataFlowConfiguration" - } + LambdaDataFlowConfiguration() { this = "LambdaDataFlowConfiguration" } override predicate isSource(DataFlow::Node source) { lambdaCapturesLoopVariable(source.asExpr(), _, _) } - override predicate isSink(DataFlow::Node sink) { - exists(getAssignmentTarget(sink.asExpr())) - } + override predicate isSink(DataFlow::Node sink) { exists(getAssignmentTarget(sink.asExpr())) } - predicate capturesLoopVarAndIsStoredIn(AnonymousFunctionExpr lambda, Variable loopVar, Element storage) { - exists(DataFlow::Node sink | - this.hasFlow(DataFlow::exprNode(lambda), sink) | + predicate capturesLoopVarAndIsStoredIn( + AnonymousFunctionExpr lambda, Variable loopVar, Element storage + ) { + exists(DataFlow::Node sink | this.hasFlow(DataFlow::exprNode(lambda), sink) | storage = getAssignmentTarget(sink.asExpr()) - ) - and - exists(ForeachStmt loop | - lambdaCapturesLoopVariable(lambda, loop, loopVar) | + ) and + exists(ForeachStmt loop | lambdaCapturesLoopVariable(lambda, loop, loopVar) | not declaredInsideLoop(loop, storage) ) } } Element getAssignmentTarget(Expr e) { - exists(Assignment a | - a.getRValue() = e | + exists(Assignment a | a.getRValue() = e | result = a.getLValue().(PropertyAccess).getTarget() or result = a.getLValue().(FieldAccess).getTarget() or result = a.getLValue().(LocalVariableAccess).getTarget() or @@ -84,19 +74,16 @@ Element getAssignmentTarget(Expr e) { Element getCollectionAssignmentTarget(Expr e) { // Store into collection via method - exists(MethodCall mc, Method m, IEnumerableFlow ief, CallableFlowSourceArg source, CallableFlowSinkQualifier sink, int i | - mc.getQualifier() = result.(Variable).getAnAccess() - and - ief = mc.getQualifier().getType().getSourceDeclaration() - and - m = mc.getTarget().getSourceDeclaration() - and - ief.callableFlow(source, sink, m, _) - and - source.getCallable() = m - and - source.getArgumentIndex() = i - and + exists( + MethodCall mc, Method m, IEnumerableFlow ief, CallableFlowSourceArg source, + CallableFlowSinkQualifier sink, int i + | + mc.getQualifier() = result.(Variable).getAnAccess() and + ief = mc.getQualifier().getType().getSourceDeclaration() and + m = mc.getTarget().getSourceDeclaration() and + ief.callableFlow(source, sink, m, _) and + source.getCallable() = m and + source.getArgumentIndex() = i and e = mc.getArgument(i) ) or @@ -104,26 +91,29 @@ Element getCollectionAssignmentTarget(Expr e) { e = result.(ArrayCreation).getInitializer().getAnElement() or // Collection initializer - e = result.(ObjectCreation).getInitializer().(CollectionInitializer).getElementInitializer(_).getAnArgument() + e = result + .(ObjectCreation) + .getInitializer() + .(CollectionInitializer) + .getElementInitializer(_) + .getAnArgument() or // Store values using indexer exists(IndexerAccess ia, AssignExpr ae | - ia.getQualifier() = result.(Variable).getAnAccess() - and - ia = ae.getLValue() - and + ia.getQualifier() = result.(Variable).getAnAccess() and + ia = ae.getLValue() and e = ae.getRValue() ) } // Variable v is declared inside the loop body predicate declaredInsideLoop(ForeachStmt loop, LocalVariable v) { - exists(LocalVariableDeclStmt decl | - decl.getVariableDeclExpr(_).getVariable() = v | + exists(LocalVariableDeclStmt decl | decl.getVariableDeclExpr(_).getVariable() = v | inForeachStmtBody(loop, decl) ) } from LambdaDataFlowConfiguration c, AnonymousFunctionExpr lambda, Variable loopVar, Element storage where c.capturesLoopVarAndIsStoredIn(lambda, loopVar, storage) -select lambda, "Function which may be stored in $@ captures variable $@", storage, storage.toString(), loopVar, loopVar.getName() +select lambda, "Function which may be stored in $@ captures variable $@", storage, + storage.toString(), loopVar, loopVar.getName() diff --git a/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql b/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql index 150f9662643..bb8d54fbce4 100644 --- a/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql +++ b/csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql @@ -13,8 +13,7 @@ import csharp predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) { - def.getTarget().getSourceDeclaration() = f - and + def.getTarget().getSourceDeclaration() = f and ( def.getEnclosingCallable().(Constructor).getDeclaringType() = f.getDeclaringType() or @@ -23,15 +22,15 @@ predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) { } predicate canBeReadonly(Field f) { - forex(AssignableDefinition def | - def.getTarget().getSourceDeclaration() = f | + forex(AssignableDefinition def | def.getTarget().getSourceDeclaration() = f | isReadonlyCompatibleDefinition(def, f) ) } from Field f -where canBeReadonly(f) - and not f.isConst() - and not f.isReadOnly() - and (f.isEffectivelyPrivate() or f.isEffectivelyInternal()) +where + canBeReadonly(f) and + not f.isConst() and + not f.isReadOnly() and + (f.isEffectivelyPrivate() or f.isEffectivelyInternal()) select f, "Field '" + f.getName() + "' can be 'readonly'." diff --git a/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql b/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql index 80c467a3de5..f58abc2a566 100644 --- a/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql +++ b/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql @@ -13,25 +13,21 @@ import csharp import semmle.code.csharp.commons.StructuralComparison class StructuralComparisonConfig extends StructuralComparisonConfiguration { - StructuralComparisonConfig() { - this = "MissedTernaryOpportunity" - } + StructuralComparisonConfig() { this = "MissedTernaryOpportunity" } override predicate candidate(Element x, Element y) { exists(IfStmt is, AssignExpr ae1 | - ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr() | - x = ae1.getLValue() - and - exists(AssignExpr ae2 | - ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() | + ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr() + | + x = ae1.getLValue() and + exists(AssignExpr ae2 | ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() | y = ae2.getLValue() ) ) } IfStmt getIfStmt() { - exists(AssignExpr ae | - ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() | + exists(AssignExpr ae | ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() | same(ae.getLValue(), _) ) } @@ -41,14 +37,16 @@ from IfStmt is, string what where ( ( - is.getThen().stripSingletonBlocks() instanceof ReturnStmt - and is.getElse().stripSingletonBlocks() instanceof ReturnStmt - and what = "return" + is.getThen().stripSingletonBlocks() instanceof ReturnStmt and + is.getElse().stripSingletonBlocks() instanceof ReturnStmt and + what = "return" ) - or exists(StructuralComparisonConfig c | - is = c.getIfStmt() - and what = "write to the same variable" + or + exists(StructuralComparisonConfig c | + is = c.getIfStmt() and + what = "write to the same variable" ) - ) - and not exists(IfStmt other | is = other.getElse()) -select is, "Both branches of this 'if' statement " + what + " - consider using '?' to express intent better." + ) and + not exists(IfStmt other | is = other.getElse()) +select is, + "Both branches of this 'if' statement " + what + " - consider using '?' to express intent better." diff --git a/csharp/ql/src/Language Abuse/MissedUsingOpportunity.ql b/csharp/ql/src/Language Abuse/MissedUsingOpportunity.ql index dbc1bad54d6..5fdcfb64eee 100644 --- a/csharp/ql/src/Language Abuse/MissedUsingOpportunity.ql +++ b/csharp/ql/src/Language Abuse/MissedUsingOpportunity.ql @@ -13,27 +13,22 @@ import csharp import semmle.code.csharp.frameworks.System /** A call to IDisposable.Dispose or a method that overrides it. */ -class DisposeCall extends MethodCall -{ - DisposeCall() - { - getTarget() instanceof DisposeMethod - } +class DisposeCall extends MethodCall { + DisposeCall() { getTarget() instanceof DisposeMethod } /** The object being disposed by the call (provided it can be easily determined). */ - Variable getDisposee() - { + Variable getDisposee() { exists(VariableAccess va | - va = getQualifier().stripCasts() - and result = va.getTarget() + va = getQualifier().stripCasts() and + result = va.getTarget() ) } } from Variable v, DisposeCall c, TryStmt ts where - v = c.getDisposee() - and c = ts.getFinally().getAChild*() -select v, "This variable is manually $@ in a $@ - consider a C# using statement as a preferable resource management technique.", - c, "disposed", - ts.getFinally(), "finally block" + v = c.getDisposee() and + c = ts.getFinally().getAChild*() +select v, + "This variable is manually $@ in a $@ - consider a C# using statement as a preferable resource management technique.", + c, "disposed", ts.getFinally(), "finally block" diff --git a/csharp/ql/src/Language Abuse/NestedIf.ql b/csharp/ql/src/Language Abuse/NestedIf.ql index ef4c2abf8a4..4532fbbebee 100644 --- a/csharp/ql/src/Language Abuse/NestedIf.ql +++ b/csharp/ql/src/Language Abuse/NestedIf.ql @@ -13,9 +13,7 @@ import csharp from IfStmt outer, IfStmt inner where - inner = outer.getThen().stripSingletonBlocks() -and - not exists(outer.getElse()) -and + inner = outer.getThen().stripSingletonBlocks() and + not exists(outer.getElse()) and not exists(inner.getElse()) select outer, "These 'if' statements can be combined." diff --git a/csharp/ql/src/Language Abuse/RethrowException.ql b/csharp/ql/src/Language Abuse/RethrowException.ql index bc5399c8916..bd3e2902907 100644 --- a/csharp/ql/src/Language Abuse/RethrowException.ql +++ b/csharp/ql/src/Language Abuse/RethrowException.ql @@ -13,19 +13,18 @@ import csharp -CatchClause containingCatchClause(Stmt s) -{ +CatchClause containingCatchClause(Stmt s) { result.getBlock() = s or exists(Stmt mid | - result = containingCatchClause(mid) - and - mid.getAChildStmt() = s - and - not mid instanceof CatchClause) + result = containingCatchClause(mid) and + mid.getAChildStmt() = s and + not mid instanceof CatchClause + ) } from SpecificCatchClause cc, ThrowStmt throw -where throw.getExpr() = cc.getVariable().getAnAccess() -and containingCatchClause(throw) = cc +where + throw.getExpr() = cc.getVariable().getAnAccess() and + containingCatchClause(throw) = cc select throw, "Rethrowing exception variable." diff --git a/csharp/ql/src/Language Abuse/SimplifyBoolExpr.ql b/csharp/ql/src/Language Abuse/SimplifyBoolExpr.ql index af643f3bf5b..a8ce9c42065 100644 --- a/csharp/ql/src/Language Abuse/SimplifyBoolExpr.ql +++ b/csharp/ql/src/Language Abuse/SimplifyBoolExpr.ql @@ -16,8 +16,7 @@ import csharp * No other child nodes are boolean literals. */ predicate literalChild(Expr expr, int child, boolean value) { - value = expr.getChild(child).(BoolLiteral).getBoolValue() - and + value = expr.getChild(child).(BoolLiteral).getBoolValue() and forall(int c | c != child | not expr.getChild(c) instanceof BoolLiteral) } @@ -26,10 +25,8 @@ predicate literalChild(Expr expr, int child, boolean value) { * No other child nodes are boolean literals. */ predicate literalChildren(Expr expr, int child1, boolean value1, int child2, boolean value2) { - value1 = expr.getChild(child1).(BoolLiteral).getBoolValue() - and - value2 = expr.getChild(child2).(BoolLiteral).getBoolValue() - and + value1 = expr.getChild(child1).(BoolLiteral).getBoolValue() and + value2 = expr.getChild(child2).(BoolLiteral).getBoolValue() and forall(int c | c != child1 and c != child2 | not expr.getChild(c) instanceof BoolLiteral) } @@ -40,7 +37,10 @@ predicate rewriteBinaryExpr(BinaryOperation op, boolean value, string oldPattern } bindingset[withFalseOperand, withTrueOperand] -predicate rewriteBinaryExpr(BinaryOperation op, string oldPattern, string withFalseOperand, string withTrueOperand, string newPattern) { +predicate rewriteBinaryExpr( + BinaryOperation op, string oldPattern, string withFalseOperand, string withTrueOperand, + string newPattern +) { rewriteBinaryExpr(op, false, oldPattern) and newPattern = withFalseOperand or rewriteBinaryExpr(op, true, oldPattern) and newPattern = withTrueOperand @@ -55,7 +55,9 @@ predicate rewriteConditionalExpr(ConditionalExpr cond, string oldPattern, string or literalChild(cond, 2, true) and oldPattern = "A ? B : true" and newPattern = "!A || B" or - exists(boolean b | literalChildren(cond, 1, b, 2, b) | oldPattern = "A ? " + b + " : " + b and newPattern = b.toString()) + exists(boolean b | literalChildren(cond, 1, b, 2, b) | + oldPattern = "A ? " + b + " : " + b and newPattern = b.toString() + ) or literalChildren(cond, 1, true, 2, false) and oldPattern = "A ? true : false" and newPattern = "A" or @@ -86,19 +88,18 @@ predicate pushNegation(LogicalNotExpr expr, string oldPattern, string newPattern expr.getOperand() instanceof LogicalNotExpr and oldPattern = "!!A" and newPattern = "A" or exists(string oldOperator, string newOperator | - oldOperator = expr.getOperand().(BinaryOperation).getOperator() - and + oldOperator = expr.getOperand().(BinaryOperation).getOperator() and negatedOperators(oldOperator, newOperator) - | - oldPattern = "!(A " + oldOperator + " B)" - and + | + oldPattern = "!(A " + oldOperator + " B)" and newPattern = "A " + newOperator + " B" ) } predicate rewrite(Expr expr, string oldPattern, string newPattern) { exists(string withFalseOperand, string withTrueOperand | - simplifyBinaryExpr(expr.(BinaryOperation).getOperator(), withFalseOperand, withTrueOperand) | + simplifyBinaryExpr(expr.(BinaryOperation).getOperator(), withFalseOperand, withTrueOperand) + | rewriteBinaryExpr(expr, oldPattern, withFalseOperand, withTrueOperand, newPattern) ) or @@ -108,8 +109,9 @@ predicate rewrite(Expr expr, string oldPattern, string newPattern) { } from Expr expr, string oldPattern, string newPattern, string action -where rewrite(expr, oldPattern, newPattern) - and if newPattern = "true" or newPattern = "false" +where + rewrite(expr, oldPattern, newPattern) and + if newPattern = "true" or newPattern = "false" then action = "is always" else action = "can be simplified to" select expr, "The expression '" + oldPattern + "' " + action + " '" + newPattern + "'." diff --git a/csharp/ql/src/Language Abuse/UnusedPropertyValue.ql b/csharp/ql/src/Language Abuse/UnusedPropertyValue.ql index 90c250e5cfb..d1c2e9566fd 100644 --- a/csharp/ql/src/Language Abuse/UnusedPropertyValue.ql +++ b/csharp/ql/src/Language Abuse/UnusedPropertyValue.ql @@ -14,10 +14,11 @@ import csharp from Setter setter -where not exists(setter.getAParameter().getAnAccess()) -and not exists(ThrowStmt t | t.getEnclosingCallable()=setter) -and setter.hasBody() // Trivial setter is OK -and not setter.getDeclaration().overrides() -and not setter.getDeclaration().implements() -and not setter.getDeclaration().isVirtual() +where + not exists(setter.getAParameter().getAnAccess()) and + not exists(ThrowStmt t | t.getEnclosingCallable() = setter) and + setter.hasBody() and // Trivial setter is OK + not setter.getDeclaration().overrides() and + not setter.getDeclaration().implements() and + not setter.getDeclaration().isVirtual() select setter, "Value ignored when setting property." diff --git a/csharp/ql/src/Language Abuse/UselessCastToSelf.ql b/csharp/ql/src/Language Abuse/UselessCastToSelf.ql index f820b329a95..a182009dfc2 100644 --- a/csharp/ql/src/Language Abuse/UselessCastToSelf.ql +++ b/csharp/ql/src/Language Abuse/UselessCastToSelf.ql @@ -13,9 +13,10 @@ import csharp from ExplicitCast cast, Expr e, Type type -where e = cast.getExpr() - and type = cast.getTargetType() - and type = e.getType() - and not type instanceof NullType - and not e.(ImplicitDelegateCreation).getArgument() instanceof AnonymousFunctionExpr +where + e = cast.getExpr() and + type = cast.getTargetType() and + type = e.getType() and + not type instanceof NullType and + not e.(ImplicitDelegateCreation).getArgument() instanceof AnonymousFunctionExpr select cast, "This cast is redundant because the expression already has type " + type + "." diff --git a/csharp/ql/src/Language Abuse/UselessIsBeforeAs.ql b/csharp/ql/src/Language Abuse/UselessIsBeforeAs.ql index 8663bd70fa1..c2997037272 100644 --- a/csharp/ql/src/Language Abuse/UselessIsBeforeAs.ql +++ b/csharp/ql/src/Language Abuse/UselessIsBeforeAs.ql @@ -14,20 +14,15 @@ import csharp import semmle.code.csharp.commons.StructuralComparison class StructuralComparisonConfig extends StructuralComparisonConfiguration { - StructuralComparisonConfig() { - this = "UselessIsBeforeAs" - } + StructuralComparisonConfig() { this = "UselessIsBeforeAs" } override predicate candidate(Element x, Element y) { exists(IfStmt is, AsExpr ae, IsTypeExpr ie | - ie = is.getCondition().getAChild*() - and - ae.getTargetType() = ie.getCheckedType() - and - x = ie.getExpr() - and + ie = is.getCondition().getAChild*() and + ae.getTargetType() = ie.getCheckedType() and + x = ie.getExpr() and y = ae.getExpr() - | + | ae = is.getThen().getAChild*() or ae = is.getElse().getAChild*() @@ -36,10 +31,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration { predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) { exists(Expr x, Expr y | - same(x, y) - and - ie.getExpr() = x - and + same(x, y) and + ie.getExpr() = x and ae.getExpr() = y ) } @@ -47,8 +40,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration { from AsExpr ae, IsExpr ie where - exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) - and + exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) and not exists(MethodCall mc | ae = mc.getAnArgument().getAChildExpr*()) -select ae, "This 'as' expression performs a type test - it should be directly compared against null, rendering the 'is' $@ potentially redundant.", +select ae, + "This 'as' expression performs a type test - it should be directly compared against null, rendering the 'is' $@ potentially redundant.", ie, "here" diff --git a/csharp/ql/src/Language Abuse/UselessNullCoalescingExpression.ql b/csharp/ql/src/Language Abuse/UselessNullCoalescingExpression.ql index 9e4cf91ff59..3e5bc514e59 100644 --- a/csharp/ql/src/Language Abuse/UselessNullCoalescingExpression.ql +++ b/csharp/ql/src/Language Abuse/UselessNullCoalescingExpression.ql @@ -15,23 +15,19 @@ import csharp import semmle.code.csharp.commons.StructuralComparison class StructuralComparisonConfig extends StructuralComparisonConfiguration { - StructuralComparisonConfig() { - this = "UselessNullCoalescingExpression" - } + StructuralComparisonConfig() { this = "UselessNullCoalescingExpression" } override predicate candidate(Element x, Element y) { exists(NullCoalescingExpr nce | - x.(Access) = nce.getLeftOperand() - and + x.(Access) = nce.getLeftOperand() and y.(Access) = nce.getRightOperand().getAChildExpr*() ) } NullCoalescingExpr getUselessNullCoalescingExpr() { exists(AssignableAccess x | - result.getLeftOperand() = x - and - forex(AssignableAccess y | same(x,y) | y instanceof AssignableRead and not y.isRefArgument()) + result.getLeftOperand() = x and + forex(AssignableAccess y | same(x, y) | y instanceof AssignableRead and not y.isRefArgument()) ) } } diff --git a/csharp/ql/src/Language Abuse/UselessTypeTest.ql b/csharp/ql/src/Language Abuse/UselessTypeTest.ql index a72467dfbd3..564296f0f38 100644 --- a/csharp/ql/src/Language Abuse/UselessTypeTest.ql +++ b/csharp/ql/src/Language Abuse/UselessTypeTest.ql @@ -14,9 +14,9 @@ import csharp from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct where - t = ise.getExpr().getType() - and ct = ise.getCheckedType() - and ct = t.getABaseType+() -select ise, "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", - t, t.getName(), - ct, ct.getName() + t = ise.getExpr().getType() and + ct = ise.getCheckedType() and + ct = t.getABaseType+() +select ise, + "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t, + t.getName(), ct, ct.getName() diff --git a/csharp/ql/src/Language Abuse/UselessUpcast.ql b/csharp/ql/src/Language Abuse/UselessUpcast.ql index d601c23a3b4..55cfb69c591 100644 --- a/csharp/ql/src/Language Abuse/UselessUpcast.ql +++ b/csharp/ql/src/Language Abuse/UselessUpcast.ql @@ -13,17 +13,11 @@ import csharp /** A static callable. */ -class StaticCallable extends Callable { - StaticCallable() { - this.(Modifiable).isStatic() - } -} +class StaticCallable extends Callable { StaticCallable() { this.(Modifiable).isStatic() } } /** An instance callable, that is, a non-static callable. */ class InstanceCallable extends Callable { - InstanceCallable() { - not this instanceof StaticCallable - } + InstanceCallable() { not this instanceof StaticCallable } } /** A call to a static callable. */ @@ -35,21 +29,21 @@ class StaticCall extends Call { } /** Holds `t` has instance callable `c` as a member, with name `name`. */ -pragma [noinline] +pragma[noinline] predicate hasInstanceCallable(ValueOrRefType t, InstanceCallable c, string name) { t.hasMember(c) and name = c.getName() } /** Holds if extension method `m` is a method on `t` with name `name`. */ -pragma [noinline] +pragma[noinline] predicate hasExtensionMethod(ValueOrRefType t, ExtensionMethod m, string name) { t.isImplicitlyConvertibleTo(m.getExtendedType()) and name = m.getName() } /** Holds `t` has static callable `c` as a member, with name `name`. */ -pragma [noinline] +pragma[noinline] predicate hasStaticCallable(ValueOrRefType t, StaticCallable c, string name) { t.hasMember(c) and name = c.getName() @@ -58,9 +52,9 @@ predicate hasStaticCallable(ValueOrRefType t, StaticCallable c, string name) { /** Gets the minimum number of arguments required to call `c`. */ int getMinimumArguments(Callable c) { result = count(Parameter p | - p = c.getAParameter() and - not p.hasDefaultValue() - ) + p = c.getAParameter() and + not p.hasDefaultValue() + ) } /** Gets the maximum number of arguments allowed to call `c`, if any. */ @@ -72,6 +66,7 @@ int getMaximumArguments(Callable c) { /** An explicit upcast. */ class ExplicitUpcast extends ExplicitCast { ValueOrRefType src; + ValueOrRefType dest; ExplicitUpcast() { @@ -93,10 +88,9 @@ class ExplicitUpcast extends ExplicitCast { } /** Holds if this upcast may be used to disambiguate the target of an instance call. */ - pragma [nomagic] + pragma[nomagic] private predicate isDisambiguatingInstanceCall(InstanceCallable other, int args) { - exists(Call c, InstanceCallable target, ValueOrRefType t | - this.isArgument(c, target) | + exists(Call c, InstanceCallable target, ValueOrRefType t | this.isArgument(c, target) | t = c.(QualifiableExpr).getQualifier().getType() and hasInstanceCallable(t, other, target.getName()) and args = c.getNumberOfArguments() and @@ -105,10 +99,11 @@ class ExplicitUpcast extends ExplicitCast { } /** Holds if this upcast may be used to disambiguate the target of an extension method call. */ - pragma [nomagic] + pragma[nomagic] private predicate isDisambiguatingExtensionCall(ExtensionMethod other, int args) { exists(ExtensionMethodCall c, ExtensionMethod target, ValueOrRefType t | - this.isArgument(c, target) | + this.isArgument(c, target) + | not c.isOrdinaryStaticCall() and t = target.getParameter(0).getType() and hasExtensionMethod(t, other, target.getName()) and @@ -117,8 +112,10 @@ class ExplicitUpcast extends ExplicitCast { ) } - pragma [nomagic] - private predicate isDisambiguatingStaticCall0(StaticCall c, StaticCallable target, string name, ValueOrRefType t) { + pragma[nomagic] + private predicate isDisambiguatingStaticCall0( + StaticCall c, StaticCallable target, string name, ValueOrRefType t + ) { this.isArgument(c, target) and name = target.getName() and ( @@ -130,10 +127,11 @@ class ExplicitUpcast extends ExplicitCast { } /** Holds if this upcast may be used to disambiguate the target of a static call. */ - pragma [nomagic] + pragma[nomagic] private predicate isDisambiguatingStaticCall(StaticCallable other, int args) { exists(StaticCall c, StaticCallable target, ValueOrRefType t, string name | - this.isDisambiguatingStaticCall0(c, target, name, t) | + this.isDisambiguatingStaticCall0(c, target, name, t) + | hasStaticCallable(t, other, name) and args = c.getNumberOfArguments() and other != target @@ -148,7 +146,7 @@ class ExplicitUpcast extends ExplicitCast { this.isDisambiguatingExtensionCall(other, args) or this.isDisambiguatingStaticCall(other, args) - | + | args >= getMinimumArguments(other) and not args > getMaximumArguments(other) ) @@ -164,29 +162,27 @@ class ExplicitUpcast extends ExplicitCast { this = any(OperatorCall oc).getAnArgument() or this = any(Operation o | - not o instanceof Assignment and - not o instanceof UnaryBitwiseOperation and - not o instanceof SizeofExpr and - not o instanceof PointerIndirectionExpr and - not o instanceof AddressOfExpr and - not o instanceof UnaryLogicalOperation and - not o instanceof BinaryBitwiseOperation and - not o instanceof LogicalAndExpr and - not o instanceof LogicalOrExpr - ).getAnOperand() + not o instanceof Assignment and + not o instanceof UnaryBitwiseOperation and + not o instanceof SizeofExpr and + not o instanceof PointerIndirectionExpr and + not o instanceof AddressOfExpr and + not o instanceof UnaryLogicalOperation and + not o instanceof BinaryBitwiseOperation and + not o instanceof LogicalAndExpr and + not o instanceof LogicalOrExpr + ).getAnOperand() or - this = any(LocalVariableDeclAndInitExpr decl | - decl.isImplicitlyTyped() - ).getInitializer() + this = any(LocalVariableDeclAndInitExpr decl | decl.isImplicitlyTyped()).getInitializer() or exists(LambdaExpr c | c.canReturn(this)) } } from ExplicitUpcast u, ValueOrRefType src, ValueOrRefType dest -where src = u.getSourceType() - and dest = u.getTargetType() - and not u.isUseful() -select u, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", - src, src.getName(), - dest, dest.getName() +where + src = u.getSourceType() and + dest = u.getTargetType() and + not u.isUseful() +select u, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", src, + src.getName(), dest, dest.getName() diff --git a/csharp/ql/src/Likely Bugs/BadCheckOdd.ql b/csharp/ql/src/Likely Bugs/BadCheckOdd.ql index f8836393f7f..ccaccb1a60e 100755 --- a/csharp/ql/src/Likely Bugs/BadCheckOdd.ql +++ b/csharp/ql/src/Likely Bugs/BadCheckOdd.ql @@ -9,6 +9,7 @@ * @tags reliability * correctness */ + import csharp predicate isDefinitelyPositive(Expr e) { @@ -18,11 +19,16 @@ predicate isDefinitelyPositive(Expr e) { } from BinaryOperation t, RemExpr lhs, IntegerLiteral rhs, string parity -where t.getLeftOperand() = lhs and - t.getRightOperand() = rhs and - not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and - lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and - ((t instanceof EQExpr and rhs.getValue() = "1" and parity = "oddness") or - (t instanceof NEExpr and rhs.getValue() = "1" and parity = "evenness") or - (t instanceof GTExpr and rhs.getValue() = "0" and parity = "oddness")) +where + t.getLeftOperand() = lhs and + t.getRightOperand() = rhs and + not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and + lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and + ( + (t instanceof EQExpr and rhs.getValue() = "1" and parity = "oddness") + or + (t instanceof NEExpr and rhs.getValue() = "1" and parity = "evenness") + or + (t instanceof GTExpr and rhs.getValue() = "0" and parity = "oddness") + ) select t, "Possibly invalid test for " + parity + ". This will fail for negative numbers." diff --git a/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql b/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql index e337aef3b1f..ba7a9d55754 100644 --- a/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql +++ b/csharp/ql/src/Likely Bugs/Collections/ContainerLengthCmpOffByOne.ql @@ -9,7 +9,7 @@ * @tags reliability * correctness * logic - * external/cwe/cwe-193 + * external/cwe/cwe-193 */ import csharp @@ -19,14 +19,15 @@ import semmle.code.csharp.commons.ComparisonTest /** A comparison of an index variable with the length of an array. */ class IndexGuard extends ComparisonTest { VariableAccess indexAccess; + Variable array; IndexGuard() { this.getFirstArgument() = indexAccess and this.getSecondArgument() = any(PropertyAccess lengthAccess | - lengthAccess.getQualifier() = array.getAnAccess() and - lengthAccess.getTarget().hasName("Length") - ) + lengthAccess.getQualifier() = array.getAnAccess() and + lengthAccess.getTarget().hasName("Length") + ) } /** Holds if this comparison applies to array `arr` and index `ind`. */ @@ -41,12 +42,12 @@ class IndexGuard extends ComparisonTest { } /** Holds if this comparison is an incorrect `<=` or equivalent. */ - predicate isIncorrect() { - this.getComparisonKind().isLessThanEquals() - } + predicate isIncorrect() { this.getComparisonKind().isLessThanEquals() } } -from IndexGuard incorrectGuard, Variable array, Variable index, ElementAccess ea, GuardedExpr indexAccess +from + IndexGuard incorrectGuard, Variable array, Variable index, ElementAccess ea, + GuardedExpr indexAccess where // Look for `index <= array.Length` or `array.Length >= index` incorrectGuard.controls(array, index) and @@ -63,4 +64,6 @@ where validGuard.controls(array, index) and validGuard.guards(indexAccess, _) ) -select incorrectGuard, "Off-by-one index comparison against length leads to possible out of bounds $@.", ea, ea.toString() +select incorrectGuard, + "Off-by-one index comparison against length leads to possible out of bounds $@.", ea, + ea.toString() diff --git a/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql b/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql index b2aa8afe162..5b6a5f646b7 100644 --- a/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql +++ b/csharp/ql/src/Likely Bugs/Collections/ContainerSizeCmpZero.ql @@ -9,46 +9,80 @@ * correctness * logic */ + import csharp import semmle.code.csharp.commons.Assertions private predicate propertyOverrides(Property p, string baseClass, string property) { - exists (Property p2 | p2.getSourceDeclaration().getDeclaringType().hasQualifiedName(baseClass) and - p2.hasName(property) | - p.overridesOrImplementsOrEquals(p2)) + exists(Property p2 | + p2.getSourceDeclaration().getDeclaringType().hasQualifiedName(baseClass) and + p2.hasName(property) + | + p.overridesOrImplementsOrEquals(p2) + ) } private predicate containerSizeAccess(PropertyAccess pa, string containerKind) { - ((propertyOverrides(pa.getTarget(), "System.Collections.Generic.ICollection<>", "Count") or - propertyOverrides(pa.getTarget(), "System.Collections.Generic.IReadOnlyCollection<>", "Count") or - propertyOverrides(pa.getTarget(), "System.Collections.ICollection", "Count")) and - containerKind = "a collection") or - ((propertyOverrides(pa.getTarget(), "System.String", "Length") and containerKind = "a string") or - (propertyOverrides(pa.getTarget(), "System.Array", "Length") and containerKind = "an array")) + ( + ( + propertyOverrides(pa.getTarget(), "System.Collections.Generic.ICollection<>", "Count") or + propertyOverrides(pa.getTarget(), "System.Collections.Generic.IReadOnlyCollection<>", "Count") or + propertyOverrides(pa.getTarget(), "System.Collections.ICollection", "Count") + ) and + containerKind = "a collection" + ) + or + ( + (propertyOverrides(pa.getTarget(), "System.String", "Length") and containerKind = "a string") + or + (propertyOverrides(pa.getTarget(), "System.Array", "Length") and containerKind = "an array") + ) } -class ZeroLiteral extends Expr { - ZeroLiteral() { - getValue() = "0" - } -} +class ZeroLiteral extends Expr { ZeroLiteral() { getValue() = "0" } } /** * Whether `smaller` is checked to be no greater than `greater` by `e` being `trueOrFalse` */ -private predicate checkedLT(BinaryOperation e, Expr greater, Expr smaller, string trueOrFalse) { - (greater = e.(GEExpr).getLeftOperand() and smaller = e.(GEExpr).getRightOperand() and trueOrFalse = "true") or - (greater = e.(LEExpr).getRightOperand() and smaller = e.(LEExpr).getLeftOperand() and trueOrFalse = "true") or - (greater = e.(GTExpr).getRightOperand() and smaller = e.(GTExpr).getLeftOperand() and trueOrFalse = "false") or - (greater = e.(LTExpr).getLeftOperand() and smaller = e.(LTExpr).getRightOperand() and trueOrFalse = "false") +private predicate checkedLT(BinaryOperation e, Expr greater, Expr smaller, string trueOrFalse) { + ( + greater = e.(GEExpr).getLeftOperand() and + smaller = e.(GEExpr).getRightOperand() and + trueOrFalse = "true" + ) + or + ( + greater = e.(LEExpr).getRightOperand() and + smaller = e.(LEExpr).getLeftOperand() and + trueOrFalse = "true" + ) + or + ( + greater = e.(GTExpr).getRightOperand() and + smaller = e.(GTExpr).getLeftOperand() and + trueOrFalse = "false" + ) + or + ( + greater = e.(LTExpr).getLeftOperand() and + smaller = e.(LTExpr).getRightOperand() and + trueOrFalse = "false" + ) } - -private predicate comparisonOfContainerSizeToZero(BinaryOperation e, string containerKind, string trueOrFalse) { - exists (Expr sizeAccess | containerSizeAccess(sizeAccess,containerKind) and checkedLT(e, sizeAccess, any(ZeroLiteral zl), trueOrFalse)) +private predicate comparisonOfContainerSizeToZero( + BinaryOperation e, string containerKind, string trueOrFalse +) { + exists(Expr sizeAccess | + containerSizeAccess(sizeAccess, containerKind) and + checkedLT(e, sizeAccess, any(ZeroLiteral zl), trueOrFalse) + ) } from BinaryOperation e, string containerKind, string trueOrFalse -where comparisonOfContainerSizeToZero(e, containerKind, trueOrFalse) - and not isExprInAssertion(e) -select e, "This expression is always " + trueOrFalse + ", since " + containerKind + " can never have negative size." +where + comparisonOfContainerSizeToZero(e, containerKind, trueOrFalse) and + not isExprInAssertion(e) +select e, + "This expression is always " + trueOrFalse + ", since " + containerKind + + " can never have negative size." diff --git a/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql b/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql index 84f452def43..edb5642814c 100644 --- a/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql +++ b/csharp/ql/src/Likely Bugs/Collections/ReadOnlyContainer.ql @@ -16,22 +16,20 @@ import semmle.code.csharp.commons.Collections from Variable v where - v.fromSource() - and v.getType() instanceof CollectionType - + v.fromSource() and + v.getType() instanceof CollectionType and // Publics might get assigned elsewhere - and (v instanceof LocalVariable or v.(Field).isPrivate()) - + (v instanceof LocalVariable or v.(Field).isPrivate()) and // All initializers (if any) are empty collections. - and forall( AssignableDefinition d | v = d.getTarget() | d.getSource() instanceof EmptyCollectionCreation ) - + forall(AssignableDefinition d | v = d.getTarget() | + d.getSource() instanceof EmptyCollectionCreation + ) and // All accesses do not add data. - and forex( Access a | v.getAnAccess()=a | a instanceof NoAddAccess or a instanceof EmptyInitializationAccess) - + forex(Access a | v.getAnAccess() = a | + a instanceof NoAddAccess or a instanceof EmptyInitializationAccess + ) and // Attributes indicate some kind of reflection - and (not exists( Attribute a | v=a.getTarget() )) - + (not exists(Attribute a | v = a.getTarget())) and // There is at least one non-assignment access - and v.getAnAccess() instanceof NoAddAccess + v.getAnAccess() instanceof NoAddAccess select v, "The contents of this container are never initialized." - diff --git a/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql b/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql index 5fab438fbb4..e4112b71b1f 100644 --- a/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql +++ b/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql @@ -14,15 +14,18 @@ import csharp import semmle.code.csharp.commons.Collections from Variable v -where v.getType() instanceof CollectionType - and (v instanceof LocalVariable or v = any(Field f | f.isEffectivelyPrivate() or f.isEffectivelyInternal())) - and forex(Access a | - a = v.getAnAccess() | +where + v.getType() instanceof CollectionType and + ( + v instanceof LocalVariable or + v = any(Field f | f.isEffectivelyPrivate() or f.isEffectivelyInternal()) + ) and + forex(Access a | a = v.getAnAccess() | a = any(ModifierMethodCall m).getQualifier() or a = any(Assignment ass | ass.getRValue() instanceof ObjectCreation).getLValue() - ) - and not v = any(ForeachStmt fs).getVariable() - and not v = any(IsPatternExpr ipe).getVariableDeclExpr().getVariable() - and not v = any(TypeCase tc).getVariableDeclExpr().getVariable() - and not v = any(Attribute a).getTarget() + ) and + not v = any(ForeachStmt fs).getVariable() and + not v = any(IsPatternExpr ipe).getVariableDeclExpr().getVariable() and + not v = any(TypeCase tc).getVariableDeclExpr().getVariable() and + not v = any(Attribute a).getTarget() select v, "The contents of this container are never accessed." diff --git a/csharp/ql/src/Likely Bugs/ConstantComparison.ql b/csharp/ql/src/Likely Bugs/ConstantComparison.ql index 9f10fd46f01..790cb53e80b 100644 --- a/csharp/ql/src/Likely Bugs/ConstantComparison.ql +++ b/csharp/ql/src/Likely Bugs/ConstantComparison.ql @@ -13,7 +13,8 @@ import semmle.code.csharp.commons.Assertions import semmle.code.csharp.commons.Constants from ComparisonOperation cmp, boolean value -where isConstantComparison(cmp, value) - and not isConstantCondition(cmp, _) // Avoid overlap with cs/constant-condition - and not isExprInAssertion(cmp) +where + isConstantComparison(cmp, value) and + not isConstantCondition(cmp, _) and // Avoid overlap with cs/constant-condition + not isExprInAssertion(cmp) select cmp, "This comparison is always " + value + "." diff --git a/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql b/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql index 48dea670ea9..f8fcc1d1e12 100644 --- a/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql +++ b/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql @@ -18,12 +18,9 @@ import csharp /** An expression containing a qualified member access, a method call, or an array access. */ class DangerousExpression extends Expr { DangerousExpression() { - exists(Expr e | - this = e.getParent*() | - exists(Expr q | - q = e.(MemberAccess).getQualifier() | - not q instanceof ThisAccess - and + exists(Expr e | this = e.getParent*() | + exists(Expr q | q = e.(MemberAccess).getQualifier() | + not q instanceof ThisAccess and not q instanceof BaseAccess ) or @@ -41,14 +38,10 @@ class NonShortCircuit extends BinaryBitwiseOperation { this instanceof BitwiseAndExpr or this instanceof BitwiseOrExpr - ) - and - not exists(AssignBitwiseOperation abo | abo.getExpandedAssignment().getRValue() = this) - and - getLeftOperand().getType() instanceof BoolType - and - getRightOperand().getType() instanceof BoolType - and + ) and + not exists(AssignBitwiseOperation abo | abo.getExpandedAssignment().getRValue() = this) and + getLeftOperand().getType() instanceof BoolType and + getRightOperand().getType() instanceof BoolType and getRightOperand() instanceof DangerousExpression } } diff --git a/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql b/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql index 3d187be6079..b54cdef50f0 100644 --- a/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql +++ b/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql @@ -20,8 +20,7 @@ abstract class BadDynamicCall extends DynamicExpr { abstract AssignableRead getARelevantVariableAccess(int i); Type possibleBadTypeForRelevantSource(Variable v, int i, Expr source) { - exists(Type t | - t = possibleTypeForRelevantSource(v, i, source) | + exists(Type t | t = possibleTypeForRelevantSource(v, i, source) | // If the source can have the type of an interface or an abstract class, // then all possible sub types are, in principle, possible t instanceof Interface and result.isImplicitlyConvertibleTo(t) @@ -29,11 +28,11 @@ abstract class BadDynamicCall extends DynamicExpr { t.(Class).isAbstract() and result.isImplicitlyConvertibleTo(t) or result = t - ) - and not result instanceof Interface - and not result.(Class).isAbstract() - and not result instanceof NullType - and not result instanceof DynamicType + ) and + not result instanceof Interface and + not result.(Class).isAbstract() and + not result instanceof NullType and + not result instanceof DynamicType } private Type possibleTypeForRelevantSource(Variable v, int i, Expr source) { @@ -42,79 +41,65 @@ abstract class BadDynamicCall extends DynamicExpr { v = read.getTarget() and result = source.getType() and read = ssaDef.getARead() and - ultimateSsaDef = ssaDef.getAnUltimateDefinition() | + ultimateSsaDef = ssaDef.getAnUltimateDefinition() + | ultimateSsaDef.getADefinition() = any(AssignableDefinition def | - source = def.getSource().stripImplicitCasts() - ) + source = def.getSource().stripImplicitCasts() + ) or ultimateSsaDef.getADefinition() = any(AssignableDefinitions::ImplicitParameterDefinition p | - source = p.getParameter().getAnAssignedValue().stripImplicitCasts() - ) + source = p.getParameter().getAnAssignedValue().stripImplicitCasts() + ) ) } } class BadDynamicMethodCall extends BadDynamicCall, DynamicMethodCall { - override AssignableRead getARelevantVariableAccess(int i) { - result = getQualifier() and i = -1 - } + override AssignableRead getARelevantVariableAccess(int i) { result = getQualifier() and i = -1 } override predicate isBad(Variable v, ValueOrRefType pt, Expr pts, string message, string target) { - pt = possibleBadTypeForRelevantSource(v, -1, pts) - and - not exists(Method m | - m = getARuntimeTarget() | + pt = possibleBadTypeForRelevantSource(v, -1, pts) and + not exists(Method m | m = getARuntimeTarget() | pt.isImplicitlyConvertibleTo(m.getDeclaringType()) - ) - and - message = "The $@ of this dynamic method invocation can obtain (from $@) type $@, which does not have a method '" + getLateBoundTargetName() + "' with the appropriate signature." - and + ) and + message = "The $@ of this dynamic method invocation can obtain (from $@) type $@, which does not have a method '" + + getLateBoundTargetName() + "' with the appropriate signature." and target = "target" } } class BadDynamicOperatorCall extends BadDynamicCall, DynamicOperatorCall { - override AssignableRead getARelevantVariableAccess(int i) { - result = getRuntimeArgument(i) - } + override AssignableRead getARelevantVariableAccess(int i) { result = getRuntimeArgument(i) } override predicate isBad(Variable v, ValueOrRefType pt, Expr pts, string message, string target) { exists(int i | - pt = possibleBadTypeForRelevantSource(v, i, pts) - and - not pt.containsTypeParameters() - and - not exists(Operator o, Type paramType | - paramType = getADynamicParameterType(o, i) | + pt = possibleBadTypeForRelevantSource(v, i, pts) and + not pt.containsTypeParameters() and + not exists(Operator o, Type paramType | paramType = getADynamicParameterType(o, i) | pt.isImplicitlyConvertibleTo(paramType) or // If either the argument type or the parameter type contains type parameters, // then assume they may match paramType.containsTypeParameters() - ) - and + ) and exists(string number | number = "first" and i = 0 or number = "second" and i = 1 - | + | target = number + " argument" ) - ) - and - message = "The $@ of this dynamic operator can obtain (from $@) type $@, which does not match an operator '" + getLateBoundTargetName() + "' with the appropriate signature." + ) and + message = "The $@ of this dynamic operator can obtain (from $@) type $@, which does not match an operator '" + + getLateBoundTargetName() + "' with the appropriate signature." } private Type getADynamicParameterType(Operator o, int i) { - o = getARuntimeTarget() - and + o = getARuntimeTarget() and result = o.getParameter(i).getType() } } from BadDynamicCall call, Variable v, ValueOrRefType pt, Expr pts, string message, string target where call.isBad(v, pt, pts, message, target) -select call, message, - v, target, - pts, "here", - pt, pt.getName() +select call, message, v, target, pts, "here", pt, pt.getName() diff --git a/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql b/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql index a3da8b65866..537691e6246 100644 --- a/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql +++ b/csharp/ql/src/Likely Bugs/EqualityCheckOnFloats.ql @@ -8,19 +8,20 @@ * @tags reliability * correctness */ + import csharp class ZeroFloatLiteral extends FloatLiteral { ZeroFloatLiteral() { - this.getValue() = "0" - or this.getValue() = "0.0" + this.getValue() = "0" or + this.getValue() = "0.0" } } from EqualityOperation e where - e.getAnOperand().getType() instanceof FloatingPointType - and not ( + e.getAnOperand().getType() instanceof FloatingPointType and + not ( e.getAnOperand() instanceof NullLiteral //Uncomment this to exclude comparisons to 0 literals //or e.getAnOperand() instanceof ZeroFloatLiteral diff --git a/csharp/ql/src/Likely Bugs/EqualsArray.ql b/csharp/ql/src/Likely Bugs/EqualsArray.ql index e0f78e6ef6f..78d86d61364 100644 --- a/csharp/ql/src/Likely Bugs/EqualsArray.ql +++ b/csharp/ql/src/Likely Bugs/EqualsArray.ql @@ -8,27 +8,26 @@ * @tags reliability * correctness */ + import csharp import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.Collections // Does method m have an override in t or one of its derived classes? pragma[nomagic] -predicate methodOverriddenBelow(Method m, Class t) -{ +predicate methodOverriddenBelow(Method m, Class t) { m.getAnOverrider*().getDeclaringType() = t.getASubType*() } -predicate isIEnumerable(ValueOrRefType t) -{ - t instanceof ArrayType // Extractor doesn't extract interfaces of ArrayType yet. - or t.getABaseInterface*() instanceof SystemCollectionsIEnumerableInterface +predicate isIEnumerable(ValueOrRefType t) { + t instanceof ArrayType or // Extractor doesn't extract interfaces of ArrayType yet. + t.getABaseInterface*() instanceof SystemCollectionsIEnumerableInterface } from MethodCall m where - m.getTarget() instanceof EqualsMethod - and isIEnumerable(m.getQualifier().getType()) - and isIEnumerable(m.getArgument(0).getType()) - and not methodOverriddenBelow(m.getTarget(), m.getQualifier().getType()) + m.getTarget() instanceof EqualsMethod and + isIEnumerable(m.getQualifier().getType()) and + isIEnumerable(m.getArgument(0).getType()) and + not methodOverriddenBelow(m.getTarget(), m.getQualifier().getType()) select m, "Using Equals(object) on a collection only checks reference equality." diff --git a/csharp/ql/src/Likely Bugs/EqualsUsesAs.ql b/csharp/ql/src/Likely Bugs/EqualsUsesAs.ql index 4dc3f70f0d4..65fc3aa9ec6 100644 --- a/csharp/ql/src/Likely Bugs/EqualsUsesAs.ql +++ b/csharp/ql/src/Likely Bugs/EqualsUsesAs.ql @@ -14,16 +14,20 @@ import semmle.code.csharp.frameworks.System from EqualsMethod m, AsExpr e, Class asType where - m.fromSource() - and e.getEnclosingCallable() = m - and e.getExpr().(VariableAccess).getTarget() = m.getParameter(0) - and asType = e.getTargetType() - and not(asType.isSealed()) - and not exists(MethodCall c, Variable v | - c.getEnclosingCallable() = m - and c.getTarget().getName() = "GetType" - and v = c.getQualifier().(VariableAccess).getTarget() | + m.fromSource() and + e.getEnclosingCallable() = m and + e.getExpr().(VariableAccess).getTarget() = m.getParameter(0) and + asType = e.getTargetType() and + not (asType.isSealed()) and + not exists(MethodCall c, Variable v | + c.getEnclosingCallable() = m and + c.getTarget().getName() = "GetType" and + v = c.getQualifier().(VariableAccess).getTarget() + | v = m.getParameter(0) or v.getAnAssignedValue() = e ) -select e, m.getDeclaringType().getName() + ".Equals(object) should not use \"as\" on its parameter, as it will not work properly for subclasses of " + asType.getName() + "." +select e, + m.getDeclaringType().getName() + + ".Equals(object) should not use \"as\" on its parameter, as it will not work properly for subclasses of " + + asType.getName() + "." diff --git a/csharp/ql/src/Likely Bugs/EqualsUsesIs.ql b/csharp/ql/src/Likely Bugs/EqualsUsesIs.ql index ebb70f1b491..f0e9631fb66 100644 --- a/csharp/ql/src/Likely Bugs/EqualsUsesIs.ql +++ b/csharp/ql/src/Likely Bugs/EqualsUsesIs.ql @@ -14,14 +14,17 @@ import semmle.code.csharp.frameworks.System from EqualsMethod m, IsTypeExpr e, Class isType where - m.fromSource() - and e.getEnclosingCallable() = m - and e.getExpr().(VariableAccess).getTarget() = m.getParameter(0) - and isType = e.getCheckedType() - and not(isType.isSealed()) - and not exists(MethodCall c | - c.getEnclosingCallable() = m - and c.getTarget().getName() = "GetType" - and c.getQualifier().(VariableAccess).getTarget() = m.getParameter(0) + m.fromSource() and + e.getEnclosingCallable() = m and + e.getExpr().(VariableAccess).getTarget() = m.getParameter(0) and + isType = e.getCheckedType() and + not (isType.isSealed()) and + not exists(MethodCall c | + c.getEnclosingCallable() = m and + c.getTarget().getName() = "GetType" and + c.getQualifier().(VariableAccess).getTarget() = m.getParameter(0) ) -select e, m.getDeclaringType().getName() + ".Equals(object) should not use \"is\" on its parameter, as it will not work properly for subclasses of " + isType.getName() + "." +select e, + m.getDeclaringType().getName() + + ".Equals(object) should not use \"is\" on its parameter, as it will not work properly for subclasses of " + + isType.getName() + "." diff --git a/csharp/ql/src/Likely Bugs/HashedButNoHash.ql b/csharp/ql/src/Likely Bugs/HashedButNoHash.ql index ea00e3cfffc..6272459ce55 100644 --- a/csharp/ql/src/Likely Bugs/HashedButNoHash.ql +++ b/csharp/ql/src/Likely Bugs/HashedButNoHash.ql @@ -8,51 +8,47 @@ * @tags reliability * maintainability */ + import csharp import semmle.code.csharp.frameworks.System -predicate dictionary(ConstructedType constructed) -{ +predicate dictionary(ConstructedType constructed) { exists(UnboundGenericType dict | dict.hasQualifiedName("System.Collections.Generic", "Dictionary<,>") and - constructed = dict.getAConstructedGeneric()) + constructed = dict.getAConstructedGeneric() + ) } -predicate hashtable(Class c) -{ - c.hasQualifiedName("System.Collections", "Hashtable") -} +predicate hashtable(Class c) { c.hasQualifiedName("System.Collections", "Hashtable") } -predicate hashstructure(Type t) -{ - hashtable(t) or dictionary(t) -} +predicate hashstructure(Type t) { hashtable(t) or dictionary(t) } -predicate hashAdd(Expr e) -{ +predicate hashAdd(Expr e) { exists(MethodCall mc, string name | (name = "Add" or name = "ContainsKey") and mc.getArgument(0) = e and mc.getTarget().hasName(name) and - hashstructure(mc.getTarget().getDeclaringType())) + hashstructure(mc.getTarget().getDeclaringType()) + ) } -predicate eqWithoutHash(RefType t) -{ - t.getAMethod() instanceof EqualsMethod - and not t.getAMethod() instanceof GetHashCodeMethod +predicate eqWithoutHash(RefType t) { + t.getAMethod() instanceof EqualsMethod and + not t.getAMethod() instanceof GetHashCodeMethod } -predicate hashCall(Expr e) -{ +predicate hashCall(Expr e) { exists(MethodCall mc | mc.getQualifier() = e and - mc.getTarget() instanceof GetHashCodeMethod) + mc.getTarget() instanceof GetHashCodeMethod + ) } from Expr e, Type t -where (hashAdd(e) or hashCall(e)) - and e.getType() = t - and eqWithoutHash(t) -select e, "This expression is hashed, but type '" + t.getName() - + "' only defines Equals(...) not GetHashCode()." +where + (hashAdd(e) or hashCall(e)) and + e.getType() = t and + eqWithoutHash(t) +select e, + "This expression is hashed, but type '" + t.getName() + + "' only defines Equals(...) not GetHashCode()." diff --git a/csharp/ql/src/Likely Bugs/ImpossibleArrayCast.ql b/csharp/ql/src/Likely Bugs/ImpossibleArrayCast.ql index be048c0f0c9..a3a9f66f3f7 100644 --- a/csharp/ql/src/Likely Bugs/ImpossibleArrayCast.ql +++ b/csharp/ql/src/Likely Bugs/ImpossibleArrayCast.ql @@ -13,8 +13,9 @@ import csharp from CastExpr ce, RefType target, RefType source -where ce.getExpr() instanceof ArrayCreation and - target = ce.getType().(ArrayType).getElementType() and - source = ce.getExpr().getType().(ArrayType).getElementType() and - target.getABaseType+() = source +where + ce.getExpr() instanceof ArrayCreation and + target = ce.getType().(ArrayType).getElementType() and + source = ce.getExpr().getType().(ArrayType).getElementType() and + target.getABaseType+() = source select ce, "Impossible downcast on array." diff --git a/csharp/ql/src/Likely Bugs/IncomparableEquals.ql b/csharp/ql/src/Likely Bugs/IncomparableEquals.ql index 2aec47bb793..14428d14dca 100644 --- a/csharp/ql/src/Likely Bugs/IncomparableEquals.ql +++ b/csharp/ql/src/Likely Bugs/IncomparableEquals.ql @@ -8,6 +8,7 @@ * @tags reliability * correctness */ + import csharp import semmle.code.csharp.frameworks.System @@ -16,40 +17,34 @@ import semmle.code.csharp.frameworks.System * the incomparable-equals call */ predicate whitelist(MethodCall mc) { - // Allow tests to verify that equals methods return false - ((MethodCall)mc.getParent*()).getTarget().hasName("IsFalse") + // Allow tests to verify that equals methods return false + (mc.getParent*().(MethodCall)).getTarget().hasName("IsFalse") } -from EqualsMethod equals, - MethodCall ma, - Type i, - Type j +from EqualsMethod equals, MethodCall ma, Type i, Type j where - ma.getTarget() = equals and - not whitelist(ma) and - - // find the source types - ma.getArgument(0).getType() = i and - ma.getQualifier().getType() = j and - - // If one of the types is object, then we know they overlap, so - // no point checking. - not i instanceof ObjectType and - not j instanceof ObjectType and - - // In standalone extraction mode, we have to test the - // weaker condition that they are unrelated classes, - // and we have enough type information to relate the two classes, - // which would normally be 'object' without extraction errors. - (extractionIsStandalone() implies i.(Class).getBaseClass*() = j.(Class).getBaseClass*()) and - - // check they are not related - not exists(ValueOrRefType k | k.getABaseType*() = j and - k.getABaseType*() = i) and - - // exclude wildcards since the check is not applicable to them - not (i instanceof TypeParameter or j instanceof TypeParameter) and - - // exclude calls of the form x.Equals(null), since they're highlighted by a different query - not (i instanceof NullType) -select ma, "Call to 'Equals()' comparing incomparable types $@ and $@.", j, j.getName(), i, i.getName() + ma.getTarget() = equals and + not whitelist(ma) and + // find the source types + ma.getArgument(0).getType() = i and + ma.getQualifier().getType() = j and + // If one of the types is object, then we know they overlap, so + // no point checking. + not i instanceof ObjectType and + not j instanceof ObjectType and + // In standalone extraction mode, we have to test the + // weaker condition that they are unrelated classes, + // and we have enough type information to relate the two classes, + // which would normally be 'object' without extraction errors. + (extractionIsStandalone() implies i.(Class).getBaseClass*() = j.(Class).getBaseClass*()) and + // check they are not related + not exists(ValueOrRefType k | + k.getABaseType*() = j and + k.getABaseType*() = i + ) and + // exclude wildcards since the check is not applicable to them + not (i instanceof TypeParameter or j instanceof TypeParameter) and + // exclude calls of the form x.Equals(null), since they're highlighted by a different query + not (i instanceof NullType) +select ma, "Call to 'Equals()' comparing incomparable types $@ and $@.", j, j.getName(), i, + i.getName() diff --git a/csharp/ql/src/Likely Bugs/InconsistentCompareTo.ql b/csharp/ql/src/Likely Bugs/InconsistentCompareTo.ql index 77dfe94ad6f..8056ddd9531 100644 --- a/csharp/ql/src/Likely Bugs/InconsistentCompareTo.ql +++ b/csharp/ql/src/Likely Bugs/InconsistentCompareTo.ql @@ -13,20 +13,17 @@ import semmle.code.csharp.frameworks.System from Class c, Method compareTo, Method compareToImpl where - c.fromSource() - and + c.fromSource() and ( compareTo = any(SystemIComparableInterface i).getCompareToMethod() or compareTo = any(SystemIComparableTInterface i).getAConstructedGeneric().getAMethod() and compareTo.getSourceDeclaration() = any(SystemIComparableTInterface i).getCompareToMethod() - ) - and - compareToImpl = c.getAMethod() - and - compareToImpl = compareTo.getAnUltimateImplementor() - and - not compareToImpl.isAbstract() - and - not c.getAMethod() = any(SystemObjectClass o).getEqualsMethod().getAnOverrider+() -select c, "Class " + c.getName() + " implements CompareTo but does not override Equals; the two could be inconsistent." + ) and + compareToImpl = c.getAMethod() and + compareToImpl = compareTo.getAnUltimateImplementor() and + not compareToImpl.isAbstract() and + not c.getAMethod() = any(SystemObjectClass o).getEqualsMethod().getAnOverrider+() +select c, + "Class " + c.getName() + + " implements CompareTo but does not override Equals; the two could be inconsistent." diff --git a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql index a7fce8d2157..aa0ffa0736b 100644 --- a/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql +++ b/csharp/ql/src/Likely Bugs/NestedLoopsSameVariable.ql @@ -30,8 +30,11 @@ class NestedForConditions extends SC::StructuralComparisonConfiguration { /** A nested `for` statement that shares the same iteration variable as an outer `for` statement. */ class NestedForLoopSameVariable extends ForStmt { ForStmt outer; + Variable iteration; + MutatorOperation innerUpdate; + MutatorOperation outerUpdate; NestedForLoopSameVariable() { @@ -81,16 +84,19 @@ class NestedForLoopSameVariable extends ForStmt { location.hasLocationInfo(_, startLine, _, _, _) and lineStr = startLine.toString() and result = "Nested for statement uses loop variable " + name + - " of enclosing for statement (on line " + lineStr + ")." + " of enclosing for statement (on line " + lineStr + ")." ) } /** Finds elements inside the outer loop that are no longer guarded by the loop invariant. */ - private ControlFlow::Node getAnUnguardedNode() - { + private ControlFlow::Node getAnUnguardedNode() { result.getElement().getParent+() = getOuterForStmt().getBody() and ( - result = this.getCondition().(ControlFlowElement).getAControlFlowExitNode().getAFalseSuccessor() + result = this + .getCondition() + .(ControlFlowElement) + .getAControlFlowExitNode() + .getAFalseSuccessor() or exists(ControlFlow::Node mid | mid = getAnUnguardedNode() | mid.getASuccessor() = result and diff --git a/csharp/ql/src/Likely Bugs/ObjectComparison.ql b/csharp/ql/src/Likely Bugs/ObjectComparison.ql index ff472d732fc..e1c28c2949b 100644 --- a/csharp/ql/src/Likely Bugs/ObjectComparison.ql +++ b/csharp/ql/src/Likely Bugs/ObjectComparison.ql @@ -15,40 +15,34 @@ import csharp import semmle.code.csharp.frameworks.System Expr getObjectOperand(EqualityOperation eq) { - result = eq.getAnOperand() - and + result = eq.getAnOperand() and ( - result.getType() instanceof ObjectType - or result.getType() instanceof Interface + result.getType() instanceof ObjectType or + result.getType() instanceof Interface ) } class ReferenceEqualityTestOnObject extends EqualityOperation { ReferenceEqualityTestOnObject() { // One or both of the operands has type object or interface. - exists(getObjectOperand(this)) - + exists(getObjectOperand(this)) and // Neither operand is 'null'. - and not getAnOperand() instanceof NullLiteral - - and not exists(Type t | - t = getAnOperand().stripImplicitCasts().getType() | - t instanceof NullType - or t instanceof ValueType) - + not getAnOperand() instanceof NullLiteral and + not exists(Type t | t = getAnOperand().stripImplicitCasts().getType() | + t instanceof NullType or + t instanceof ValueType + ) and // Neither operand is a constant - a reference comparison may well be intended for those. - and not getAnOperand().(FieldAccess).getTarget().isReadOnly() - and not getAnOperand().hasValue() - + not getAnOperand().(FieldAccess).getTarget().isReadOnly() and + not getAnOperand().hasValue() and // Not a short-cut test in a custom `Equals` method - and not exists(EqualsMethod m | + not exists(EqualsMethod m | getEnclosingCallable() = m and getAnOperand() instanceof ThisAccess and getAnOperand() = m.getParameter(0).getAnAccess() - ) - + ) and // Reference comparisons in Moq methods are used to define mocks - and not exists(MethodCall mc, Namespace n | + not exists(MethodCall mc, Namespace n | mc.getTarget().getDeclaringType().getNamespace().getParentNamespace*() = n and n.hasName("Moq") and not exists(n.getParentNamespace()) and @@ -57,8 +51,7 @@ class ReferenceEqualityTestOnObject extends EqualityOperation { } Expr getObjectOperand() { - result = getObjectOperand(this) - and + result = getObjectOperand(this) and // Avoid duplicate results: only include left operand if both operands // have object type (result = getRightOperand() implies not getLeftOperand() = getObjectOperand(this)) @@ -66,6 +59,9 @@ class ReferenceEqualityTestOnObject extends EqualityOperation { } from ReferenceEqualityTestOnObject scw, Expr operand, Type t -where operand = scw.getObjectOperand() - and t = operand.getType() -select scw, "Reference equality for System.Object comparisons ($@ argument has type " + t.getName() + ").", operand, "this" +where + operand = scw.getObjectOperand() and + t = operand.getType() +select scw, + "Reference equality for System.Object comparisons ($@ argument has type " + t.getName() + ").", + operand, "this" diff --git a/csharp/ql/src/Likely Bugs/PossibleLossOfPrecision.ql b/csharp/ql/src/Likely Bugs/PossibleLossOfPrecision.ql index bed09a53475..cb040e1b370 100644 --- a/csharp/ql/src/Likely Bugs/PossibleLossOfPrecision.ql +++ b/csharp/ql/src/Likely Bugs/PossibleLossOfPrecision.ql @@ -21,14 +21,16 @@ import csharp predicate convertedToFloatOrDecimal(Expr e, Type t) { exists(CastExpr cast | cast.getExpr() = e and - t = cast.getType() | + t = cast.getType() + | t instanceof FloatingPointType or t instanceof DecimalType ) or exists(BinaryArithmeticOperation op | op.getAnOperand() = e and - convertedToFloatOrDecimal(op, t) | + convertedToFloatOrDecimal(op, t) + | op instanceof AddExpr or op instanceof SubExpr or op instanceof MulExpr @@ -59,13 +61,9 @@ abstract class LossOfPrecision extends Expr { /** A division expression that may result in a loss of precision. */ class DivLossOfPrecision extends LossOfPrecision, DivExpr { - DivLossOfPrecision() { - not exactDivision(this) - } + DivLossOfPrecision() { not exactDivision(this) } - override string getMessage() { - result = "Possible loss of precision: any fraction will be lost." - } + override string getMessage() { result = "Possible loss of precision: any fraction will be lost." } } /** Holds if `e` is a constant multiplication that does not overflow. */ @@ -82,12 +80,11 @@ predicate small(MulExpr e) { /** A multiplication expression that may result in a loss of precision. */ class MulLossOfPrecision extends LossOfPrecision, MulExpr { - MulLossOfPrecision() { - not small(this) - } + MulLossOfPrecision() { not small(this) } override string getMessage() { - result = "Possible overflow: result of integer multiplication cast to " + convertedType.toStringWithTypes() + "." + result = "Possible overflow: result of integer multiplication cast to " + + convertedType.toStringWithTypes() + "." } } diff --git a/csharp/ql/src/Likely Bugs/RandomUsedOnce.ql b/csharp/ql/src/Likely Bugs/RandomUsedOnce.ql index 05723464e16..469c6a6ef94 100755 --- a/csharp/ql/src/Likely Bugs/RandomUsedOnce.ql +++ b/csharp/ql/src/Likely Bugs/RandomUsedOnce.ql @@ -13,13 +13,11 @@ import csharp -predicate generateRandomNumberMethod(string s) -{ - s="Next" or s="NextBytes" or s="NextDouble" -} +predicate generateRandomNumberMethod(string s) { s = "Next" or s = "NextBytes" or s = "NextDouble" } from ObjectCreation c, MethodCall m -where c.getType().getSourceDeclaration().(ValueOrRefType).hasQualifiedName("System","Random") and - m.getQualifier()=c and +where + c.getType().getSourceDeclaration().(ValueOrRefType).hasQualifiedName("System", "Random") and + m.getQualifier() = c and generateRandomNumberMethod(m.getTarget().getName()) select m, "Random object created and used only once." diff --git a/csharp/ql/src/Likely Bugs/RecursiveEquals.ql b/csharp/ql/src/Likely Bugs/RecursiveEquals.ql index eb4555d0407..c82c36aa50e 100644 --- a/csharp/ql/src/Likely Bugs/RecursiveEquals.ql +++ b/csharp/ql/src/Likely Bugs/RecursiveEquals.ql @@ -9,13 +9,14 @@ * @tags reliability * maintainability */ + import csharp import semmle.code.csharp.frameworks.System from EqualsMethod caller, MethodCall call where - call.getEnclosingCallable() = caller - and call.getTarget() = caller - and (call.hasQualifier() implies call.hasThisQualifier()) - and call.getArgument(0).stripCasts() = caller.getParameter(0).getAnAccess() + call.getEnclosingCallable() = caller and + call.getTarget() = caller and + (call.hasQualifier() implies call.hasThisQualifier()) and + call.getArgument(0).stripCasts() = caller.getParameter(0).getAnAccess() select call, "This call to 'Equals' is recursive: did you mean to cast the argument?" diff --git a/csharp/ql/src/Likely Bugs/RecursiveOperatorEquals.ql b/csharp/ql/src/Likely Bugs/RecursiveOperatorEquals.ql index e40dcf24aa0..fe01683578f 100644 --- a/csharp/ql/src/Likely Bugs/RecursiveOperatorEquals.ql +++ b/csharp/ql/src/Likely Bugs/RecursiveOperatorEquals.ql @@ -13,7 +13,8 @@ import csharp from Operator o, OperatorCall c where - o.hasName("==") - and c.getEnclosingCallable() = o - and c.getTarget() = o -select c, "This call to 'operator==' is recursive: often this is due to a failed attempt to perform a reference equality comparison." + o.hasName("==") and + c.getEnclosingCallable() = o and + c.getTarget() = o +select c, + "This call to 'operator==' is recursive: often this is due to a failed attempt to perform a reference equality comparison." diff --git a/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql b/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql index bc99015eaab..f038117aff3 100644 --- a/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql +++ b/csharp/ql/src/Likely Bugs/ReferenceEqualsOnValueTypes.ql @@ -9,12 +9,15 @@ * correctness * external/cwe/cwe-595 */ + import csharp import semmle.code.csharp.frameworks.System from MethodCall c, Method referenceEquals -where c.getTarget() = referenceEquals - and referenceEquals = any(SystemObjectClass o).getReferenceEqualsMethod() - and c.getArgument(0).stripCasts().getType() instanceof ValueType - and c.getArgument(1).stripCasts().getType() instanceof ValueType -select c, "'ReferenceEquals(...)' always returns false on value types - this check is at best redundant and at worst erroneous." +where + c.getTarget() = referenceEquals and + referenceEquals = any(SystemObjectClass o).getReferenceEqualsMethod() and + c.getArgument(0).stripCasts().getType() instanceof ValueType and + c.getArgument(1).stripCasts().getType() instanceof ValueType +select c, + "'ReferenceEquals(...)' always returns false on value types - this check is at best redundant and at worst erroneous." diff --git a/csharp/ql/src/Likely Bugs/SelfAssignment.ql b/csharp/ql/src/Likely Bugs/SelfAssignment.ql index 8a41c938496..0c49af285a2 100644 --- a/csharp/ql/src/Likely Bugs/SelfAssignment.ql +++ b/csharp/ql/src/Likely Bugs/SelfAssignment.ql @@ -14,22 +14,18 @@ import csharp import semmle.code.csharp.commons.StructuralComparison class StructuralComparisonConfig extends StructuralComparisonConfiguration { - StructuralComparisonConfig() { - this = "SelfAssignment" - } + StructuralComparisonConfig() { this = "SelfAssignment" } override predicate candidate(Element x, Element y) { exists(AssignExpr ae | // Member initializers are never self-assignments, in particular // not initializers such as `new C { F = F };` - not ae instanceof MemberInitializer | - ae.getLValue() = x - and + not ae instanceof MemberInitializer + | + ae.getLValue() = x and ae.getRValue() = y - ) - and - forall(Expr e | - e = x.(Expr).getAChildExpr*() | + ) and + forall(Expr e | e = x.(Expr).getAChildExpr*() | // Non-trivial property accesses may have side-effects, // so these are not considered e instanceof PropertyAccess implies e instanceof TrivialPropertyAccess @@ -38,10 +34,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration { AssignExpr getSelfAssignExpr() { exists(Expr x, Expr y | - same(x, y) - and - result.getLValue() = x - and + same(x, y) and + result.getLValue() = x and result.getRValue() = y ) } diff --git a/csharp/ql/src/Likely Bugs/Statements/EmptyBlock.ql b/csharp/ql/src/Likely Bugs/Statements/EmptyBlock.ql index 67d306ca995..1906b373e6f 100644 --- a/csharp/ql/src/Likely Bugs/Statements/EmptyBlock.ql +++ b/csharp/ql/src/Likely Bugs/Statements/EmptyBlock.ql @@ -13,17 +13,33 @@ import csharp predicate loopStmtWithEmptyBlock(BlockStmt child) { - exists(LoopStmt stmt, SourceLocation l | stmt.getAChild() = child and child.getNumberOfStmts() = 0 and child.getLocation() = l and l.getStartLine() != l.getEndLine()) + exists(LoopStmt stmt, SourceLocation l | + stmt.getAChild() = child and + child.getNumberOfStmts() = 0 and + child.getLocation() = l and + l.getStartLine() != l.getEndLine() + ) } predicate conditionalWithEmptyBlock(BlockStmt child) { - exists(IfStmt stmt | stmt.getThen() = child and child.getNumberOfStmts() = 0 and not exists(stmt.getElse())) - or exists(IfStmt stmt, SourceLocation l | stmt.getThen() = child and child.getNumberOfStmts() = 0 and exists(stmt.getElse()) and child.getLocation() = l and l.getStartLine() != l.getEndLine()) - or exists(IfStmt stmt | stmt.getElse() = child and child.getNumberOfStmts() = 0) + exists(IfStmt stmt | + stmt.getThen() = child and child.getNumberOfStmts() = 0 and not exists(stmt.getElse()) + ) + or + exists(IfStmt stmt, SourceLocation l | + stmt.getThen() = child and + child.getNumberOfStmts() = 0 and + exists(stmt.getElse()) and + child.getLocation() = l and + l.getStartLine() != l.getEndLine() + ) + or + exists(IfStmt stmt | stmt.getElse() = child and child.getNumberOfStmts() = 0) } from BlockStmt s -where (loopStmtWithEmptyBlock(s) or conditionalWithEmptyBlock(s)) - and not exists(CommentBlock c | c.getParent() = s) - and not exists(ForStmt fs | fs.getBody() = s and exists(fs.getAnUpdate())) +where + (loopStmtWithEmptyBlock(s) or conditionalWithEmptyBlock(s)) and + not exists(CommentBlock c | c.getParent() = s) and + not exists(ForStmt fs | fs.getBody() = s and exists(fs.getAnUpdate())) select s, "Empty block." diff --git a/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql b/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql index b2b2b29333c..f335550ebc9 100755 --- a/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql +++ b/csharp/ql/src/Likely Bugs/Statements/UseBraces.ql @@ -14,65 +14,47 @@ import csharp // Iterate the control flow until we reach a Stmt -Stmt findSuccessorStmt(ControlFlow::Node n) -{ - result=n.getElement() or - not n.getElement() instanceof Stmt and result=findSuccessorStmt(n.getASuccessor()) +Stmt findSuccessorStmt(ControlFlow::Node n) { + result = n.getElement() + or + not n.getElement() instanceof Stmt and result = findSuccessorStmt(n.getASuccessor()) } // Return a successor statement to s -Stmt getASuccessorStmt(Stmt s) -{ - result=findSuccessorStmt(s.getAControlFlowNode().getASuccessor()) +Stmt getASuccessorStmt(Stmt s) { + result = findSuccessorStmt(s.getAControlFlowNode().getASuccessor()) } -class IfThenStmt extends IfStmt -{ - IfThenStmt() - { - not exists(Stmt s | getElse()=s) - } -} +class IfThenStmt extends IfStmt { IfThenStmt() { not exists(Stmt s | getElse() = s) } } -class IfThenElseStmt extends IfStmt -{ - IfThenElseStmt() - { - exists(Stmt s | getElse()=s) - } -} +class IfThenElseStmt extends IfStmt { IfThenElseStmt() { exists(Stmt s | getElse() = s) } } -Stmt getTrailingBody(Stmt s) -{ - result=s.(ForStmt).getBody() or - result=s.(ForeachStmt).getBody() or - result=s.(WhileStmt).getBody() or - result=s.(IfThenStmt).getThen() or - result=s.(IfThenElseStmt).getElse() +Stmt getTrailingBody(Stmt s) { + result = s.(ForStmt).getBody() or + result = s.(ForeachStmt).getBody() or + result = s.(WhileStmt).getBody() or + result = s.(IfThenStmt).getThen() or + result = s.(IfThenElseStmt).getElse() } // Any control statement which has a trailing block // which could cause indentation confusion -abstract class UnbracedControlStmt extends Stmt -{ +abstract class UnbracedControlStmt extends Stmt { abstract Stmt getBody(); + abstract Stmt getSuccessorStmt(); private Stmt getACandidate() { - getSuccessorStmt() = result - and getBlockStmt(this) = getBlockStmt(result) + getSuccessorStmt() = result and + getBlockStmt(this) = getBlockStmt(result) } - private Location getBodyLocation() { - result = getBody().getLocation() - } + private Location getBodyLocation() { result = getBody().getLocation() } pragma[noopt] Stmt getAConfusingTrailingStmt() { - result = getACandidate() - and - exists(Location l1, Location l2 | - l1 = getBodyLocation() and l2 = result.getLocation() | + result = getACandidate() and + exists(Location l1, Location l2 | l1 = getBodyLocation() and l2 = result.getLocation() | // This test is slightly unreliable // because tabs are counted as 1 column. // But it's accurate enough to be useful, and will @@ -83,52 +65,39 @@ abstract class UnbracedControlStmt extends Stmt } } -class UnbracedIfStmt extends UnbracedControlStmt -{ - UnbracedIfStmt() - { +class UnbracedIfStmt extends UnbracedControlStmt { + UnbracedIfStmt() { this instanceof IfStmt and not getTrailingBody(this) instanceof BlockStmt and not getTrailingBody(this) instanceof IfStmt } - override Stmt getBody() - { - result=getTrailingBody(this) - } + override Stmt getBody() { result = getTrailingBody(this) } - override Stmt getSuccessorStmt() - { + override Stmt getSuccessorStmt() { result = getASuccessorStmt(getBody()) and - result!=this + result != this } } -class UnbracedLoopStmt extends UnbracedControlStmt -{ - UnbracedLoopStmt() - { +class UnbracedLoopStmt extends UnbracedControlStmt { + UnbracedLoopStmt() { this instanceof LoopStmt and not this instanceof DoStmt and not getTrailingBody(this) instanceof BlockStmt } - override Stmt getBody() - { - result=getTrailingBody(this) - } + override Stmt getBody() { result = getTrailingBody(this) } - override Stmt getSuccessorStmt() - { + override Stmt getSuccessorStmt() { result = getASuccessorStmt(this) and result != getBody() } } -BlockStmt getBlockStmt(Element e) -{ +BlockStmt getBlockStmt(Element e) { result = e.getParent() or - result = getBlockStmt(e.(IfStmt).getParent()) // Handle chained ifs + result = getBlockStmt(e.(IfStmt).getParent()) // Handle chained ifs } from UnbracedControlStmt s, Stmt n diff --git a/csharp/ql/src/Likely Bugs/StaticFieldWrittenByInstance.ql b/csharp/ql/src/Likely Bugs/StaticFieldWrittenByInstance.ql index e5dde1fc0cb..3912a99d779 100644 --- a/csharp/ql/src/Likely Bugs/StaticFieldWrittenByInstance.ql +++ b/csharp/ql/src/Likely Bugs/StaticFieldWrittenByInstance.ql @@ -11,13 +11,15 @@ * maintainability * modularity */ + import csharp from FieldWrite fw, Field f, Callable m -where fw.getTarget() = f and - f.isStatic() and - m = fw.getEnclosingCallable() and - not m.(Member).isStatic() and - f.getDeclaringType() = m.getDeclaringType() and - m.fromSource() -select (VariableAccess)fw, "Write to static field from instance method or constructor." +where + fw.getTarget() = f and + f.isStatic() and + m = fw.getEnclosingCallable() and + not m.(Member).isStatic() and + f.getDeclaringType() = m.getDeclaringType() and + m.fromSource() +select fw.(VariableAccess), "Write to static field from instance method or constructor." diff --git a/csharp/ql/src/Likely Bugs/StringBuilderCharInit.ql b/csharp/ql/src/Likely Bugs/StringBuilderCharInit.ql index 9471e2415eb..f2d0a61efe2 100644 --- a/csharp/ql/src/Likely Bugs/StringBuilderCharInit.ql +++ b/csharp/ql/src/Likely Bugs/StringBuilderCharInit.ql @@ -12,8 +12,9 @@ import semmle.code.csharp.frameworks.system.Text from ObjectCreation c, Expr argument -where c.getObjectType() instanceof SystemTextStringBuilderClass -and argument = c.getAnArgument().stripCasts() -and argument.getType() instanceof CharType -select argument, "A character value passed to 'new StringBuilder()' is interpreted as the buffer capacity." - +where + c.getObjectType() instanceof SystemTextStringBuilderClass and + argument = c.getAnArgument().stripCasts() and + argument.getType() instanceof CharType +select argument, + "A character value passed to 'new StringBuilder()' is interpreted as the buffer capacity." diff --git a/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql b/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql index 5732cd76407..5d2ef55cd1f 100644 --- a/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql +++ b/csharp/ql/src/Likely Bugs/UncheckedCastInEquals.ql @@ -12,8 +12,7 @@ import csharp import semmle.code.csharp.frameworks.System -predicate nodeBeforeParameterAccess(ControlFlow::Node node) -{ +predicate nodeBeforeParameterAccess(ControlFlow::Node node) { exists(EqualsMethod equals | equals.getBody() = node.getElement()) or exists(EqualsMethod equals, Parameter param, ControlFlow::Node mid | @@ -21,11 +20,13 @@ predicate nodeBeforeParameterAccess(ControlFlow::Node node) equals.getAChild*() = mid.getElement() and nodeBeforeParameterAccess(mid) and not param.getAnAccess() = mid.getElement() and - mid.getASuccessor() = node) + mid.getASuccessor() = node + ) } from ParameterAccess access, CastExpr cast -where access = cast.getAChild() - and access.getTarget().getDeclaringElement() = access.getEnclosingCallable() - and nodeBeforeParameterAccess(access.getAControlFlowNode()) +where + access = cast.getAChild() and + access.getTarget().getDeclaringElement() = access.getEnclosingCallable() and + nodeBeforeParameterAccess(access.getAControlFlowNode()) select cast, "Missing type-check before casting parameter to 'Equals'." diff --git a/csharp/ql/src/Linq/BadMultipleIteration.ql b/csharp/ql/src/Linq/BadMultipleIteration.ql index 11072ae7a64..4dc3f0df883 100644 --- a/csharp/ql/src/Linq/BadMultipleIteration.ql +++ b/csharp/ql/src/Linq/BadMultipleIteration.ql @@ -15,52 +15,50 @@ import csharp import Helpers /** The enumerable sequence is likely not to be repeatable. */ -predicate likelyNonRepeatableSequence(IEnumerableSequence seq) -{ +predicate likelyNonRepeatableSequence(IEnumerableSequence seq) { // The source of the sequence is one of: exists(Expr src | src = sequenceSource(seq) | // A call to a method that both returns an IEnumerable and calls ReadLine. exists(MethodCall mc | - mc = src - and isIEnumerableType(mc.getTarget().getReturnType()) - and exists(MethodCall readlineCall | - readlineCall.getTarget().hasName("ReadLine") - and readlineCall.getEnclosingCallable() = mc.getTarget() + mc = src and + isIEnumerableType(mc.getTarget().getReturnType()) and + exists(MethodCall readlineCall | + readlineCall.getTarget().hasName("ReadLine") and + readlineCall.getEnclosingCallable() = mc.getTarget() ) ) - + or // A call to Select(...) that instantiates new objects. - or exists(SelectCall sc | - sc = src - and sc.getFunctionExpr().getExpressionBody() instanceof ObjectCreation + exists(SelectCall sc | + sc = src and + sc.getFunctionExpr().getExpressionBody() instanceof ObjectCreation ) ) } /** An access to an enumerable sequence that potentially consumes sequence elements. */ -predicate potentiallyConsumingAccess(VariableAccess va) -{ - exists(ForeachStmt fes | - va = fes.getIterableExpr() - ) - or exists(MethodCall mc | - va = mc.getArgument(0) - and mc.getTarget() instanceof ExtensionMethod +predicate potentiallyConsumingAccess(VariableAccess va) { + exists(ForeachStmt fes | va = fes.getIterableExpr()) + or + exists(MethodCall mc | + va = mc.getArgument(0) and + mc.getTarget() instanceof ExtensionMethod ) } /** The source of an enumerable sequence (an expression used to initialise it, or the right-hand side of an assignment to it). */ -Expr sequenceSource(IEnumerableSequence seq) -{ +Expr sequenceSource(IEnumerableSequence seq) { result = seq.getInitializer() - or exists(Assignment a | a.getLValue() = seq.getAnAccess() and result = a.getRValue()) + or + exists(Assignment a | a.getLValue() = seq.getAnAccess() and result = a.getRValue()) } from IEnumerableSequence seq, VariableAccess va where - likelyNonRepeatableSequence(seq) - and va = seq.getAnAccess() - and potentiallyConsumingAccess(va) - and count(VariableAccess x | x = seq.getAnAccess() and potentiallyConsumingAccess(x)) > 1 -select seq, "This enumerable sequence may not be repeatable, but is potentially consumed multiple times $@.", + likelyNonRepeatableSequence(seq) and + va = seq.getAnAccess() and + potentiallyConsumingAccess(va) and + count(VariableAccess x | x = seq.getAnAccess() and potentiallyConsumingAccess(x)) > 1 +select seq, + "This enumerable sequence may not be repeatable, but is potentially consumed multiple times $@.", va, "here" diff --git a/csharp/ql/src/Linq/MissedAllOpportunity.ql b/csharp/ql/src/Linq/MissedAllOpportunity.ql index d46c9788198..6bed4d41b65 100644 --- a/csharp/ql/src/Linq/MissedAllOpportunity.ql +++ b/csharp/ql/src/Linq/MissedAllOpportunity.ql @@ -14,23 +14,24 @@ import csharp import Helpers /* -The purpose of this query is to find loops of the following form: - -bool allEven = true; -foreach(int i in lst) -{ - if(i % 2 != 0) - { - allEven = false; - break; - } -} - -This could be written more cleanly as: - -bool allEven = lst.All(i => i % 2 == 0); -*/ + * The purpose of this query is to find loops of the following form: + * + * bool allEven = true; + * foreach(int i in lst) + * { + * if(i % 2 != 0) + * { + * allEven = false; + * break; + * } + * } + * + * This could be written more cleanly as: + * + * bool allEven = lst.All(i => i % 2 == 0); + */ from ForeachStmt fes where missedAllOpportunity(fes) -select fes, "This foreach loop looks as if it might be testing whether every sequence element satisfies a predicate - consider using '.All(...)'." +select fes, + "This foreach loop looks as if it might be testing whether every sequence element satisfies a predicate - consider using '.All(...)'." diff --git a/csharp/ql/src/Linq/MissedCastOpportunity.ql b/csharp/ql/src/Linq/MissedCastOpportunity.ql index ec7a3083996..50dcd63e933 100644 --- a/csharp/ql/src/Linq/MissedCastOpportunity.ql +++ b/csharp/ql/src/Linq/MissedCastOpportunity.ql @@ -15,5 +15,6 @@ import Helpers from ForeachStmt fes, LocalVariableDeclStmt s where missedCastOpportunity(fes, s) -select fes, "This foreach loop immediately casts its iteration variable to another type $@ - consider casting the sequence explicitly using '.Cast(...)'.", +select fes, + "This foreach loop immediately casts its iteration variable to another type $@ - consider casting the sequence explicitly using '.Cast(...)'.", s, "here" diff --git a/csharp/ql/src/Linq/MissedOfTypeOpportunity.ql b/csharp/ql/src/Linq/MissedOfTypeOpportunity.ql index abd598982b3..7b4ce2f83c0 100644 --- a/csharp/ql/src/Linq/MissedOfTypeOpportunity.ql +++ b/csharp/ql/src/Linq/MissedOfTypeOpportunity.ql @@ -15,5 +15,6 @@ import Helpers from ForeachStmt fes, LocalVariableDeclStmt s where missedOfTypeOpportunity(fes, s) -select fes, "This foreach loop immediately uses 'as' to coerce its iteration variable to another type $@ - consider using '.OfType(...)' instead.", +select fes, + "This foreach loop immediately uses 'as' to coerce its iteration variable to another type $@ - consider using '.OfType(...)' instead.", s, "here" diff --git a/csharp/ql/src/Linq/MissedSelectOpportunity.ql b/csharp/ql/src/Linq/MissedSelectOpportunity.ql index f56d9e90a1a..f8cb386531c 100644 --- a/csharp/ql/src/Linq/MissedSelectOpportunity.ql +++ b/csharp/ql/src/Linq/MissedSelectOpportunity.ql @@ -13,17 +13,17 @@ import csharp import Helpers -predicate oversized(LocalVariableDeclStmt s) -{ +predicate oversized(LocalVariableDeclStmt s) { exists(Location loc | - loc = s.getLocation() - and loc.getEndColumn() - loc.getStartColumn() > 65 + loc = s.getLocation() and + loc.getEndColumn() - loc.getStartColumn() > 65 ) } from ForeachStmt fes, LocalVariableDeclStmt s where - missedSelectOpportunity(fes, s) - and not(oversized(s)) -select fes, "This foreach loop immediately maps its iteration variable to another variable $@ - consider mapping the sequence explicitly using '.Select(...)'.", + missedSelectOpportunity(fes, s) and + not (oversized(s)) +select fes, + "This foreach loop immediately maps its iteration variable to another variable $@ - consider mapping the sequence explicitly using '.Select(...)'.", s, "here" diff --git a/csharp/ql/src/Linq/MissedWhereOpportunity.ql b/csharp/ql/src/Linq/MissedWhereOpportunity.ql index f32fd5df255..631cc88d7b6 100644 --- a/csharp/ql/src/Linq/MissedWhereOpportunity.ql +++ b/csharp/ql/src/Linq/MissedWhereOpportunity.ql @@ -14,7 +14,8 @@ import Helpers from ForeachStmt fes, IfStmt is where - missedWhereOpportunity(fes, is) - and not missedAllOpportunity(fes) -select fes, "This foreach loop implicitly filters its target sequence $@ - consider filtering the sequence explicitly using '.Where(...)'.", + missedWhereOpportunity(fes, is) and + not missedAllOpportunity(fes) +select fes, + "This foreach loop implicitly filters its target sequence $@ - consider filtering the sequence explicitly using '.Where(...)'.", is.getCondition(), "here" diff --git a/csharp/ql/src/Linq/RedundantSelect.ql b/csharp/ql/src/Linq/RedundantSelect.ql index 0613664f476..c43872e5979 100644 --- a/csharp/ql/src/Linq/RedundantSelect.ql +++ b/csharp/ql/src/Linq/RedundantSelect.ql @@ -13,10 +13,9 @@ import csharp import Helpers -predicate isIdentityFunction(AnonymousFunctionExpr afe) -{ - afe.getNumberOfParameters() = 1 - and afe.getExpressionBody() = afe.getParameter(0).getAnAccess() +predicate isIdentityFunction(AnonymousFunctionExpr afe) { + afe.getNumberOfParameters() = 1 and + afe.getExpressionBody() = afe.getParameter(0).getAnAccess() } from SelectCall sc diff --git a/csharp/ql/src/Metrics/Callables/CCyclomaticComplexity.ql b/csharp/ql/src/Metrics/Callables/CCyclomaticComplexity.ql index 5ce320670e0..24c5fbb7dfc 100644 --- a/csharp/ql/src/Metrics/Callables/CCyclomaticComplexity.ql +++ b/csharp/ql/src/Metrics/Callables/CCyclomaticComplexity.ql @@ -10,9 +10,9 @@ * maintainability * @id cs/cyclomatic-complexity-per-function */ + import csharp from Callable c where c.isSourceDeclaration() -select c, c.getCyclomaticComplexity() as n -order by n desc +select c, c.getCyclomaticComplexity() as n order by n desc diff --git a/csharp/ql/src/Metrics/Callables/CLinesOfCode.ql b/csharp/ql/src/Metrics/Callables/CLinesOfCode.ql index 394c751824a..0242c35d692 100644 --- a/csharp/ql/src/Metrics/Callables/CLinesOfCode.ql +++ b/csharp/ql/src/Metrics/Callables/CLinesOfCode.ql @@ -9,9 +9,9 @@ * complexity * @id cs/lines-of-code-per-function */ + import csharp from Callable c where c.isSourceDeclaration() -select c, c.getNumberOfLinesOfCode() as n -order by n desc +select c, c.getNumberOfLinesOfCode() as n order by n desc diff --git a/csharp/ql/src/Metrics/Callables/CLinesOfComment.ql b/csharp/ql/src/Metrics/Callables/CLinesOfComment.ql index 33ef38646bb..0c22d5d50b7 100644 --- a/csharp/ql/src/Metrics/Callables/CLinesOfComment.ql +++ b/csharp/ql/src/Metrics/Callables/CLinesOfComment.ql @@ -9,9 +9,9 @@ * documentation * @id cs/lines-of-comment-per-function */ + import csharp from Callable c where c.isSourceDeclaration() -select c, c.getNumberOfLinesOfComments() as n -order by n desc +select c, c.getNumberOfLinesOfComments() as n order by n desc diff --git a/csharp/ql/src/Metrics/Callables/CNumberOfParameters.ql b/csharp/ql/src/Metrics/Callables/CNumberOfParameters.ql index 940efe9c949..0d0ccc0eb6b 100644 --- a/csharp/ql/src/Metrics/Callables/CNumberOfParameters.ql +++ b/csharp/ql/src/Metrics/Callables/CNumberOfParameters.ql @@ -10,9 +10,9 @@ * maintainability * @id cs/parameters-per-function */ + import csharp from Callable c where c.isSourceDeclaration() -select c, c.getNumberOfParameters() as n -order by n desc +select c, c.getNumberOfParameters() as n order by n desc diff --git a/csharp/ql/src/Metrics/Callables/CNumberOfStatements.ql b/csharp/ql/src/Metrics/Callables/CNumberOfStatements.ql index 785ff3282ec..e3371fa2044 100644 --- a/csharp/ql/src/Metrics/Callables/CNumberOfStatements.ql +++ b/csharp/ql/src/Metrics/Callables/CNumberOfStatements.ql @@ -3,17 +3,19 @@ * @description Counts the number of statements nesting in each callable element (callables are methods, constructors, operators, accessors, ...). * @kind treemap * @treemap.warnOn highValues - * @treemap.warnOn highValues * @metricType callable * @metricAggregate avg sum max * @tags maintainability * @id cs/statements-per-function */ + import csharp from Callable c, int n -where c.isSourceDeclaration() - and n = count(Stmt s | s.getEnclosingCallable() = c - and s != c.getAChild()) // we do not count the top-level block -select c, n -order by n desc +where + c.isSourceDeclaration() and + n = count(Stmt s | + s.getEnclosingCallable() = c and + s != c.getAChild() + ) // we do not count the top-level block +select c, n order by n desc diff --git a/csharp/ql/src/Metrics/Callables/CPercentageOfComments.ql b/csharp/ql/src/Metrics/Callables/CPercentageOfComments.ql index bf2fec31056..a55eb5368ef 100644 --- a/csharp/ql/src/Metrics/Callables/CPercentageOfComments.ql +++ b/csharp/ql/src/Metrics/Callables/CPercentageOfComments.ql @@ -9,8 +9,9 @@ * documentation * @id cs/comment-ratio-per-type */ + import csharp from Callable f, int loc where f.isSourceDeclaration() and loc = f.getNumberOfLines() and loc > 0 -select f, 100.0 * ((float)f.getNumberOfLinesOfComments() / (float)loc) +select f, 100.0 * (f.getNumberOfLinesOfComments().(float) / loc.(float)) diff --git a/csharp/ql/src/Metrics/Callables/StatementNestingDepth.ql b/csharp/ql/src/Metrics/Callables/StatementNestingDepth.ql index 123103e1f52..33dc7881b8a 100644 --- a/csharp/ql/src/Metrics/Callables/StatementNestingDepth.ql +++ b/csharp/ql/src/Metrics/Callables/StatementNestingDepth.ql @@ -9,21 +9,21 @@ * complexity * @id cs/statement-nesting-depth-per-function */ + import csharp -/** The parent of a statement, excluding some common cases that don't really make - sense for nesting depth. An example is: "if (...) { } else if (...) { }: we don't - consider the second if nested. Blocks are also skipped */ +/** + * The parent of a statement, excluding some common cases that don't really make + * sense for nesting depth. An example is: "if (...) { } else if (...) { }: we don't + * consider the second if nested. Blocks are also skipped + */ predicate realParent(Stmt inner, Stmt outer) { - if skipParent(inner) then - realParent(inner.getParent(), outer) - else - outer = inner.getParent() + if skipParent(inner) then realParent(inner.getParent(), outer) else outer = inner.getParent() } predicate skipParent(Stmt s) { exists(Stmt parent | parent = s.getParent() | - (s instanceof IfStmt and ((IfStmt)parent).getElse() = s) + (s instanceof IfStmt and (parent.(IfStmt)).getElse() = s) or parent instanceof BlockStmt ) @@ -34,6 +34,6 @@ predicate nestingDepth(Stmt s, int depth) { } from Method m, int depth -where depth = max(Stmt s, int aDepth | s.getEnclosingCallable() = m and nestingDepth(s, aDepth) | aDepth) -select m, depth -order by depth +where + depth = max(Stmt s, int aDepth | s.getEnclosingCallable() = m and nestingDepth(s, aDepth) | aDepth) +select m, depth order by depth diff --git a/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql index b8488a44607..1c2e9aaa721 100644 --- a/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/csharp/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -11,8 +11,5 @@ import semmle.code.csharp.metrics.ExternalDependencies from File file, int num, string encodedDependency -where - externalDependencies(file, encodedDependency, num) -select - encodedDependency, num -order by num desc +where externalDependencies(file, encodedDependency, num) +select encodedDependency, num order by num desc diff --git a/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index 9afd58c97c4..e9cda425592 100644 --- a/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/csharp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -8,7 +8,5 @@ import semmle.code.csharp.metrics.ExternalDependencies from File file, int num, string encodedDependency -where - externalDependencies(file, encodedDependency, num) -select - encodedDependency, file +where externalDependencies(file, encodedDependency, num) +select encodedDependency, file diff --git a/csharp/ql/src/Metrics/Files/FCommentRatio.ql b/csharp/ql/src/Metrics/Files/FCommentRatio.ql index a1ce1874aea..df1346cc16a 100644 --- a/csharp/ql/src/Metrics/Files/FCommentRatio.ql +++ b/csharp/ql/src/Metrics/Files/FCommentRatio.ql @@ -9,11 +9,13 @@ * documentation * @id cs/comment-ratio-per-file */ + import csharp from SourceFile f, int total, float ratio -where total = f.getNumberOfLinesOfCode() + f.getNumberOfLinesOfComments() - and if total = 0 then ratio = 0.0 - else ratio = 100.0 * ((float)f.getNumberOfLinesOfComments()) / ((float)total) -select f, ratio -order by ratio desc +where + total = f.getNumberOfLinesOfCode() + f.getNumberOfLinesOfComments() and + if total = 0 + then ratio = 0.0 + else ratio = 100.0 * (f.getNumberOfLinesOfComments().(float)) / (total.(float)) +select f, ratio order by ratio desc diff --git a/csharp/ql/src/Metrics/Files/FCyclomaticComplexity.ql b/csharp/ql/src/Metrics/Files/FCyclomaticComplexity.ql index e36bec078b8..a2961ebfeda 100644 --- a/csharp/ql/src/Metrics/Files/FCyclomaticComplexity.ql +++ b/csharp/ql/src/Metrics/Files/FCyclomaticComplexity.ql @@ -9,8 +9,9 @@ * complexity * @id cs/average-cyclomatic-complexity-per-file */ + import csharp -from File f, float n +from File f, float n where n = avg(Callable c | c.getFile() = f | c.getCyclomaticComplexity()) select f, n diff --git a/csharp/ql/src/Metrics/Files/FLines.ql b/csharp/ql/src/Metrics/Files/FLines.ql index 04c908c15ce..dad97929d94 100644 --- a/csharp/ql/src/Metrics/Files/FLines.ql +++ b/csharp/ql/src/Metrics/Files/FLines.ql @@ -7,8 +7,8 @@ * @metricAggregate avg sum max * @id cs/lines-per-file */ + import csharp from SourceFile f -select f, f.getNumberOfLines() as n -order by n desc +select f, f.getNumberOfLines() as n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FLinesOfCode.ql b/csharp/ql/src/Metrics/Files/FLinesOfCode.ql index d205deabef7..7aa709b2579 100644 --- a/csharp/ql/src/Metrics/Files/FLinesOfCode.ql +++ b/csharp/ql/src/Metrics/Files/FLinesOfCode.ql @@ -10,8 +10,8 @@ * @tags maintainability * complexity */ + import csharp from File f -select f, f.getNumberOfLinesOfCode() as n -order by n desc +select f, f.getNumberOfLinesOfCode() as n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FLinesOfComment.ql b/csharp/ql/src/Metrics/Files/FLinesOfComment.ql index 7086b165a72..2071b86ad7a 100644 --- a/csharp/ql/src/Metrics/Files/FLinesOfComment.ql +++ b/csharp/ql/src/Metrics/Files/FLinesOfComment.ql @@ -10,8 +10,8 @@ * @tags maintainability * documentation */ + import csharp from SourceFile f -select f, f.getNumberOfLinesOfComments() as n -order by n desc +select f, f.getNumberOfLinesOfComments() as n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FLinesOfCommentedCode.ql b/csharp/ql/src/Metrics/Files/FLinesOfCommentedCode.ql index c19219623d9..30460731e6f 100644 --- a/csharp/ql/src/Metrics/Files/FLinesOfCommentedCode.ql +++ b/csharp/ql/src/Metrics/Files/FLinesOfCommentedCode.ql @@ -14,10 +14,11 @@ import csharp from SourceFile f, int n -where n = count(CommentLine line | - exists(CommentBlock block | - block.getLocation().getFile() = f and - line = block.getAProbableCodeLine()) - ) -select f, n -order by n desc +where + n = count(CommentLine line | + exists(CommentBlock block | + block.getLocation().getFile() = f and + line = block.getAProbableCodeLine() + ) + ) +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql b/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql index ab4a1e9151a..bfaab94fb3d 100644 --- a/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql +++ b/csharp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql @@ -11,14 +11,15 @@ * @tags testability * modularity */ + import external.CodeDuplication from SourceFile f, int n -where n = count(int line | - exists(DuplicateBlock d | d.sourceFile() = f | - line in [d.sourceStartLine()..d.sourceEndLine()] and - not whitelistedLineForDuplication(f, line) +where + n = count(int line | + exists(DuplicateBlock d | d.sourceFile() = f | + line in [d.sourceStartLine() .. d.sourceEndLine()] and + not whitelistedLineForDuplication(f, line) + ) ) - ) -select f, n -order by n desc +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FNumberOfClasses.ql b/csharp/ql/src/Metrics/Files/FNumberOfClasses.ql index 225b440fa4a..2ca9274fdae 100644 --- a/csharp/ql/src/Metrics/Files/FNumberOfClasses.ql +++ b/csharp/ql/src/Metrics/Files/FNumberOfClasses.ql @@ -8,9 +8,9 @@ * @tags maintainability * @id cs/classes-per-file */ + import csharp from SourceFile f, int n where n = count(Class c | c.getFile() = f and c.isSourceDeclaration()) -select f, n -order by n desc +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FNumberOfInterfaces.ql b/csharp/ql/src/Metrics/Files/FNumberOfInterfaces.ql index 5b173ccedb2..9649612e79a 100644 --- a/csharp/ql/src/Metrics/Files/FNumberOfInterfaces.ql +++ b/csharp/ql/src/Metrics/Files/FNumberOfInterfaces.ql @@ -8,9 +8,9 @@ * @tags maintainability * @id cs/interfaces-per-file */ + import csharp from SourceFile f, int n where n = count(Interface i | i.getFile() = f and i.isSourceDeclaration()) -select f, n -order by n desc +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FNumberOfStructs.ql b/csharp/ql/src/Metrics/Files/FNumberOfStructs.ql index 011bc5b4db0..16745295e7e 100644 --- a/csharp/ql/src/Metrics/Files/FNumberOfStructs.ql +++ b/csharp/ql/src/Metrics/Files/FNumberOfStructs.ql @@ -8,9 +8,9 @@ * @tags maintainability * @id cs/structs-per-file */ + import csharp from SourceFile f, int n where n = count(Struct s | s.getFile() = f and s.isSourceDeclaration()) -select f, n -order by n desc +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FNumberOfTests.ql b/csharp/ql/src/Metrics/Files/FNumberOfTests.ql index deb12556cc3..613c76c68af 100644 --- a/csharp/ql/src/Metrics/Files/FNumberOfTests.ql +++ b/csharp/ql/src/Metrics/Files/FNumberOfTests.ql @@ -9,10 +9,10 @@ * @id cs/tests-in-files * @tags maintainability */ + import csharp import semmle.code.csharp.frameworks.Test from SourceFile f, int n where n = strictcount(TestMethod test | test.fromSource() and test.getFile() = f) -select f, n -order by n desc +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FNumberOfUsingNamespaces.ql b/csharp/ql/src/Metrics/Files/FNumberOfUsingNamespaces.ql index 41c05e0dca6..bc12feb66fd 100644 --- a/csharp/ql/src/Metrics/Files/FNumberOfUsingNamespaces.ql +++ b/csharp/ql/src/Metrics/Files/FNumberOfUsingNamespaces.ql @@ -8,9 +8,9 @@ * @tags maintainability * @id cs/using-namespaces-per-file */ + import csharp from SourceFile f, int n where n = count(UsingNamespaceDirective u | u.getFile() = f) -select f, n -order by n desc +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/Files/FSelfContainedness.ql b/csharp/ql/src/Metrics/Files/FSelfContainedness.ql index 662932bee75..6763d4881f2 100644 --- a/csharp/ql/src/Metrics/Files/FSelfContainedness.ql +++ b/csharp/ql/src/Metrics/Files/FSelfContainedness.ql @@ -9,24 +9,27 @@ * modularity * @id cs/source-dependency-ratio-per-file */ + import csharp import semmle.code.csharp.metrics.Coupling /* Self-containedness on file level */ from File f, float selfContaindness, int efferentSourceCoupling, int efferentCoupling - -where efferentSourceCoupling = count(File g| - exists(RefType c| c.fromSource() and c.getFile() = g and - exists(RefType d| d.fromSource() and d.getFile()= f and depends(d,c)) - ) - ) - and efferentCoupling = count(File g| - exists(RefType c| c.getFile() = g and - exists(RefType d| d.fromSource() and d.getFile() = f and depends(d,c)) - ) - ) -and if efferentCoupling = 0 then selfContaindness = 100 else - selfContaindness = 100*(float)efferentSourceCoupling/efferentCoupling - -select f, selfContaindness -order by selfContaindness desc +where + efferentSourceCoupling = count(File g | + exists(RefType c | + c.fromSource() and + c.getFile() = g and + exists(RefType d | d.fromSource() and d.getFile() = f and depends(d, c)) + ) + ) and + efferentCoupling = count(File g | + exists(RefType c | + c.getFile() = g and + exists(RefType d | d.fromSource() and d.getFile() = f and depends(d, c)) + ) + ) and + if efferentCoupling = 0 + then selfContaindness = 100 + else selfContaindness = 100 * efferentSourceCoupling.(float) / efferentCoupling +select f, selfContaindness order by selfContaindness desc diff --git a/csharp/ql/src/Metrics/History/HChurn.ql b/csharp/ql/src/Metrics/History/HChurn.ql index 8a433dfb0fd..cd338db4734 100644 --- a/csharp/ql/src/Metrics/History/HChurn.ql +++ b/csharp/ql/src/Metrics/History/HChurn.ql @@ -7,10 +7,15 @@ * @metricAggregate avg sum max * @id cs/vcs/churn-per-file */ + import csharp import external.VCS from File f, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentChurnForFile(f) and not artificialChange(entry) | churn) -select f, n -order by n desc +where + n = sum(Commit entry, int churn | + churn = entry.getRecentChurnForFile(f) and not artificialChange(entry) + | + churn + ) +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/History/HLinesAdded.ql b/csharp/ql/src/Metrics/History/HLinesAdded.ql index 2a96ae9b129..2c2f2ee3c76 100644 --- a/csharp/ql/src/Metrics/History/HLinesAdded.ql +++ b/csharp/ql/src/Metrics/History/HLinesAdded.ql @@ -7,10 +7,15 @@ * @metricAggregate avg sum max * @id cs/vcs/added-lines-per-file */ + import csharp import external.VCS from File f, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentAdditionsForFile(f) and not artificialChange(entry) | churn) -select f, n -order by n desc +where + n = sum(Commit entry, int churn | + churn = entry.getRecentAdditionsForFile(f) and not artificialChange(entry) + | + churn + ) +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/History/HLinesDeleted.ql b/csharp/ql/src/Metrics/History/HLinesDeleted.ql index f231a515256..b30816ca665 100644 --- a/csharp/ql/src/Metrics/History/HLinesDeleted.ql +++ b/csharp/ql/src/Metrics/History/HLinesDeleted.ql @@ -7,10 +7,15 @@ * @metricAggregate avg sum max * @id cs/vcs/deleted-lines-per-file */ + import csharp import external.VCS from File f, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentDeletionsForFile(f) and not artificialChange(entry) | churn) -select f, n -order by n desc +where + n = sum(Commit entry, int churn | + churn = entry.getRecentDeletionsForFile(f) and not artificialChange(entry) + | + churn + ) +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/History/HNumberOfAuthors.ql b/csharp/ql/src/Metrics/History/HNumberOfAuthors.ql index 5bcfd049e15..db3755597e5 100644 --- a/csharp/ql/src/Metrics/History/HNumberOfAuthors.ql +++ b/csharp/ql/src/Metrics/History/HNumberOfAuthors.ql @@ -7,9 +7,9 @@ * @metricAggregate avg min max * @id cs/vcs/authors-per-file */ + import csharp import external.VCS from File f select f, count(Author author | author.getAnEditedFile() = f) - diff --git a/csharp/ql/src/Metrics/History/HNumberOfChanges.ql b/csharp/ql/src/Metrics/History/HNumberOfChanges.ql index 47e0d8ff720..fc124f39831 100644 --- a/csharp/ql/src/Metrics/History/HNumberOfChanges.ql +++ b/csharp/ql/src/Metrics/History/HNumberOfChanges.ql @@ -7,6 +7,7 @@ * @metricAggregate avg min max sum * @id cs/vcs/commits-per-file */ + import csharp import external.VCS diff --git a/csharp/ql/src/Metrics/History/HNumberOfCoCommits.ql b/csharp/ql/src/Metrics/History/HNumberOfCoCommits.ql index 0c337438ef8..1e3bfa5e1d3 100644 --- a/csharp/ql/src/Metrics/History/HNumberOfCoCommits.ql +++ b/csharp/ql/src/Metrics/History/HNumberOfCoCommits.ql @@ -7,12 +7,11 @@ * @metricAggregate avg min max * @id cs/vcs/co-commits-per-file */ + import csharp import external.VCS -int committedFiles(Commit commit) { - result = count(commit.getAnAffectedFile()) -} +int committedFiles(Commit commit) { result = count(commit.getAnAffectedFile()) } from File f -select f, avg(Commit commit | commit.getAnAffectedFile() = f | committedFiles(commit)-1) +select f, avg(Commit commit | commit.getAnAffectedFile() = f | committedFiles(commit) - 1) diff --git a/csharp/ql/src/Metrics/History/HNumberOfReCommits.ql b/csharp/ql/src/Metrics/History/HNumberOfReCommits.ql index c7fd5ab01e1..957fe33e9f9 100644 --- a/csharp/ql/src/Metrics/History/HNumberOfReCommits.ql +++ b/csharp/ql/src/Metrics/History/HNumberOfReCommits.ql @@ -7,23 +7,27 @@ * @metricAggregate avg min max * @id cs/vcs/recommits-per-file */ + import csharp import external.VCS predicate inRange(Commit first, Commit second) { first.getAnAffectedFile() = second.getAnAffectedFile() and first != second and - exists(int n | n = first.getDate().daysTo(second.getDate()) and - n >= 0 and n < 5) + exists(int n | + n = first.getDate().daysTo(second.getDate()) and + n >= 0 and + n < 5 + ) } int recommitsForFile(File f) { result = count(Commit recommit | - f = recommit.getAnAffectedFile() and - exists(Commit prev | inRange(prev, recommit))) + f = recommit.getAnAffectedFile() and + exists(Commit prev | inRange(prev, recommit)) + ) } from File f where f.getExtension() = "c" select f, recommitsForFile(f) - diff --git a/csharp/ql/src/Metrics/History/HNumberOfRecentChanges.ql b/csharp/ql/src/Metrics/History/HNumberOfRecentChanges.ql index 548d796df35..2136f1b59cb 100644 --- a/csharp/ql/src/Metrics/History/HNumberOfRecentChanges.ql +++ b/csharp/ql/src/Metrics/History/HNumberOfRecentChanges.ql @@ -7,10 +7,13 @@ * @metricAggregate avg min max sum * @id cs/vcs/recent-commits-per-file */ + import csharp import external.VCS from File f, int n -where n = count(Commit e | e.getAnAffectedFile() = f and e.daysToNow() <= 180 and not artificialChange(e)) -select f, n -order by n desc +where + n = count(Commit e | + e.getAnAffectedFile() = f and e.daysToNow() <= 180 and not artificialChange(e) + ) +select f, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TAfferentCoupling.ql b/csharp/ql/src/Metrics/RefTypes/TAfferentCoupling.ql index 44f8c662819..3ecaff58d1a 100644 --- a/csharp/ql/src/Metrics/RefTypes/TAfferentCoupling.ql +++ b/csharp/ql/src/Metrics/RefTypes/TAfferentCoupling.ql @@ -9,9 +9,9 @@ * modularity * @id cs/incoming-type-dependencies */ + import csharp from ValueOrRefType t where t.isSourceDeclaration() -select t, t.getAfferentCoupling() as n -order by n desc +select t, t.getAfferentCoupling() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TEfferentCoupling.ql b/csharp/ql/src/Metrics/RefTypes/TEfferentCoupling.ql index 7af616ebb1c..cee2f40c12a 100644 --- a/csharp/ql/src/Metrics/RefTypes/TEfferentCoupling.ql +++ b/csharp/ql/src/Metrics/RefTypes/TEfferentCoupling.ql @@ -10,9 +10,9 @@ * maintainability * @id cs/outgoing-type-dependencies */ + import csharp from ValueOrRefType t where t.isSourceDeclaration() -select t, t.getEfferentCoupling() as n -order by n desc +select t, t.getEfferentCoupling() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TInheritanceDepth.ql b/csharp/ql/src/Metrics/RefTypes/TInheritanceDepth.ql index 36590395a03..1d063c096bc 100644 --- a/csharp/ql/src/Metrics/RefTypes/TInheritanceDepth.ql +++ b/csharp/ql/src/Metrics/RefTypes/TInheritanceDepth.ql @@ -9,9 +9,9 @@ * modularity * @id cs/inheritance-depth */ + import csharp from ValueOrRefType t where t.isSourceDeclaration() -select t, t.getInheritanceDepth() as n -order by n desc +select t, t.getInheritanceDepth() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionCK.ql b/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionCK.ql index b18b40d4559..c729004f313 100644 --- a/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionCK.ql +++ b/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionCK.ql @@ -9,9 +9,9 @@ * maintainability * @id cs/lack-of-cohesion-ck */ + import csharp from ValueOrRefType t where t.isSourceDeclaration() -select t, t.getLackOfCohesionCK() as n -order by n desc +select t, t.getLackOfCohesionCK() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionHS.ql b/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionHS.ql index 0fda99846e6..4560f87a467 100644 --- a/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionHS.ql +++ b/csharp/ql/src/Metrics/RefTypes/TLackOfCohesionHS.ql @@ -8,9 +8,9 @@ * @tags modularity * @id cs/lack-of-cohesion-hs */ + import csharp from ValueOrRefType t where t.isSourceDeclaration() -select t, t.getLackOfCohesionHS() as n -order by n desc +select t, t.getLackOfCohesionHS() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfCallables.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfCallables.ql index d0ca7c52cd9..2249507032e 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfCallables.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfCallables.ql @@ -8,13 +8,16 @@ * @tags maintainability * @id cs/functions-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and n = count(Callable c | c.getDeclaringType() = t and not c instanceof Accessor) - + count(Accessor a | a.getDeclaringType() = t - and not a.getDeclaration().(Property).isAutoImplemented() - and not a.getDeclaration().(Event).isFieldLike()) -select t, n -order by n desc +where + t.isSourceDeclaration() and + n = count(Callable c | c.getDeclaringType() = t and not c instanceof Accessor) + + count(Accessor a | + a.getDeclaringType() = t and + not a.getDeclaration().(Property).isAutoImplemented() and + not a.getDeclaration().(Event).isFieldLike() + ) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfEvents.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfEvents.ql index 549d859158d..f7d133fa074 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfEvents.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfEvents.ql @@ -8,10 +8,11 @@ * @tags maintainability * @id cs/events-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and n = count(Event e | e.getDeclaringType() = t) -select t, n -order by n desc +where + t.isSourceDeclaration() and + n = count(Event e | e.getDeclaringType() = t) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfFields.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfFields.ql index a4e82f1f9e4..ea1269f51e9 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfFields.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfFields.ql @@ -9,10 +9,11 @@ * complexity * @id cs/fields-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and n = count(Field f | f.getDeclaringType() = t and not f instanceof EnumConstant ) -select t, n -order by n desc +where + t.isSourceDeclaration() and + n = count(Field f | f.getDeclaringType() = t and not f instanceof EnumConstant) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfIndexers.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfIndexers.ql index cbb3103bd43..316763c219d 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfIndexers.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfIndexers.ql @@ -8,10 +8,11 @@ * @tags maintainability * @id cs/indexers-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and n = count(Indexer i | i.getDeclaringType() = t) -select t, n -order by n desc +where + t.isSourceDeclaration() and + n = count(Indexer i | i.getDeclaringType() = t) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfNonConstFields.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfNonConstFields.ql index f770c4087ae..b252cfa5761 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfNonConstFields.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfNonConstFields.ql @@ -7,14 +7,14 @@ * @metricAggregate avg sum max * @id cs/nonconst-fields-per-type */ + import csharp from ValueOrRefType t, int n where - t.isSourceDeclaration() - and n = count(Field f | - f.getDeclaringType() = t - and not(f instanceof MemberConstant) - ) -select t, n -order by n desc + t.isSourceDeclaration() and + n = count(Field f | + f.getDeclaringType() = t and + not (f instanceof MemberConstant) + ) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfProperties.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfProperties.ql index 8bd3394a535..0c2a0791c77 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfProperties.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfProperties.ql @@ -8,10 +8,11 @@ * @tags maintainability * @id cs/properties-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and n = count(Property p | p.getDeclaringType() = t) -select t, n -order by n desc +where + t.isSourceDeclaration() and + n = count(Property p | p.getDeclaringType() = t) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TNumberOfStatements.ql b/csharp/ql/src/Metrics/RefTypes/TNumberOfStatements.ql index 3577fb3e708..f5899b6f919 100644 --- a/csharp/ql/src/Metrics/RefTypes/TNumberOfStatements.ql +++ b/csharp/ql/src/Metrics/RefTypes/TNumberOfStatements.ql @@ -8,11 +8,14 @@ * @tags maintainability * @id cs/statements-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and n = count(Stmt s | s.getEnclosingCallable().getDeclaringType() = t - and s != s.getEnclosingCallable().getAChild()) // we do not count the top-level block -select t, n -order by n desc +where + t.isSourceDeclaration() and + n = count(Stmt s | + s.getEnclosingCallable().getDeclaringType() = t and + s != s.getEnclosingCallable().getAChild() + ) // we do not count the top-level block +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TResponse.ql b/csharp/ql/src/Metrics/RefTypes/TResponse.ql index 2d3d2fabceb..12ff37aa632 100644 --- a/csharp/ql/src/Metrics/RefTypes/TResponse.ql +++ b/csharp/ql/src/Metrics/RefTypes/TResponse.ql @@ -9,9 +9,9 @@ * complexity * @id cs/response-per-type */ + import csharp from RefType t where t.isSourceDeclaration() -select t, t.getResponse() as n -order by n desc +select t, t.getResponse() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TSizeOfAPI.ql b/csharp/ql/src/Metrics/RefTypes/TSizeOfAPI.ql index cf93e2e3359..24ccaf72f86 100644 --- a/csharp/ql/src/Metrics/RefTypes/TSizeOfAPI.ql +++ b/csharp/ql/src/Metrics/RefTypes/TSizeOfAPI.ql @@ -9,15 +9,16 @@ * modularity * @id cs/public-functions-per-type */ + import csharp from ValueOrRefType t, int n -where t.isSourceDeclaration() - and t.isPublic() - and n = count(Method m | m.getDeclaringType() = t and m.isPublic()) - + count(Operator o | o.getDeclaringType() = t and o.isPublic()) - + count(Property p | p.getDeclaringType() = t and p.isPublic()) - + count(Indexer i | i.getDeclaringType() = t and i.isPublic()) - + count(Event e | e.getDeclaringType() = t and e.isPublic()) -select t, n -order by n desc +where + t.isSourceDeclaration() and + t.isPublic() and + n = count(Method m | m.getDeclaringType() = t and m.isPublic()) + + count(Operator o | o.getDeclaringType() = t and o.isPublic()) + + count(Property p | p.getDeclaringType() = t and p.isPublic()) + + count(Indexer i | i.getDeclaringType() = t and i.isPublic()) + + count(Event e | e.getDeclaringType() = t and e.isPublic()) +select t, n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TSpecialisationIndex.ql b/csharp/ql/src/Metrics/RefTypes/TSpecialisationIndex.ql index d6b8b66fd97..7b4f211f465 100644 --- a/csharp/ql/src/Metrics/RefTypes/TSpecialisationIndex.ql +++ b/csharp/ql/src/Metrics/RefTypes/TSpecialisationIndex.ql @@ -9,9 +9,9 @@ * maintainability * @id cs/type-specialization-index */ + import csharp from RefType t where t.isSourceDeclaration() -select t, t.getSpecialisationIndex() as n -order by n desc +select t, t.getSpecialisationIndex() as n order by n desc diff --git a/csharp/ql/src/Metrics/RefTypes/TUnmanagedCode.ql b/csharp/ql/src/Metrics/RefTypes/TUnmanagedCode.ql index aac1c3c567f..ef905bfe9aa 100644 --- a/csharp/ql/src/Metrics/RefTypes/TUnmanagedCode.ql +++ b/csharp/ql/src/Metrics/RefTypes/TUnmanagedCode.ql @@ -12,6 +12,7 @@ import csharp from Class c, Method m -where m.hasModifier("extern") - and m.getDeclaringType() = c +where + m.hasModifier("extern") and + m.getDeclaringType() = c select c, 1 diff --git a/csharp/ql/src/Performance/StringBuilderInLoop.ql b/csharp/ql/src/Performance/StringBuilderInLoop.ql index 33a7b07baac..8becb0c7eb2 100644 --- a/csharp/ql/src/Performance/StringBuilderInLoop.ql +++ b/csharp/ql/src/Performance/StringBuilderInLoop.ql @@ -12,8 +12,9 @@ import csharp import semmle.code.csharp.frameworks.system.Text from ObjectCreation creation, LoopStmt loop, ControlFlow::Node loopEntryNode -where creation.getType() instanceof SystemTextStringBuilderClass - and loopEntryNode = loop.getBody().getAControlFlowEntryNode() - and loop.getBody().getAChild*() = creation - and creation.getAControlFlowNode().postDominates(loopEntryNode) +where + creation.getType() instanceof SystemTextStringBuilderClass and + loopEntryNode = loop.getBody().getAControlFlowEntryNode() and + loop.getBody().getAChild*() = creation and + creation.getAControlFlowNode().postDominates(loopEntryNode) select creation, "Creating a 'StringBuilder' in a loop." diff --git a/csharp/ql/src/Performance/StringConcatenationInLoop.ql b/csharp/ql/src/Performance/StringConcatenationInLoop.ql index 5919079db01..706a2b975d2 100644 --- a/csharp/ql/src/Performance/StringConcatenationInLoop.ql +++ b/csharp/ql/src/Performance/StringConcatenationInLoop.ql @@ -8,22 +8,20 @@ * @tags efficiency * maintainability */ + import csharp // any use of + that has string type -class StringCat extends AddExpr { - StringCat() { - this.getType() instanceof StringType - } -} +class StringCat extends AddExpr { StringCat() { this.getType() instanceof StringType } } + +/* + * an assignment of the form + * v = ... + ... v ... + * where v is a simple variable (and not, for example, a property) + */ -/* an assignment of the form - v = ... + ... v ... - where v is a simple variable (and not, for example, a property) -*/ predicate isSelfConcatAssignExpr(AssignExpr e, Variable v) { - not e = any(AssignAddExpr a).getExpandedAssignment() - and + not e = any(AssignAddExpr a).getExpandedAssignment() and exists(VariableAccess use | stringCatContains(e.getRValue(), use) and use.getTarget() = e.getTargetVariable() and @@ -36,20 +34,22 @@ predicate stringCatContains(StringCat expr, Expr child) { stringCatContains(expr, child.getParent()) } -/* an assignment of the form - v += ... - where v is a simple variable (and not, for example, a property) -*/ +/* + * an assignment of the form + * v += ... + * where v is a simple variable (and not, for example, a property) + */ + predicate isConcatExpr(AssignAddExpr e, Variable v) { e.getLValue().getType() instanceof StringType and v = e.getTargetVariable() } - from Expr e -where exists(LoopStmt loop, Variable v | - e.getEnclosingStmt().getParent*() = loop and - (isSelfConcatAssignExpr(e, v) or isConcatExpr(e, v)) and - forall(LocalVariableDeclExpr l | l.getVariable() = v | not l.getParent*() = loop) -) +where + exists(LoopStmt loop, Variable v | + e.getEnclosingStmt().getParent*() = loop and + (isSelfConcatAssignExpr(e, v) or isConcatExpr(e, v)) and + forall(LocalVariableDeclExpr l | l.getVariable() = v | not l.getParent*() = loop) + ) select e, "String concatenation in loop: use 'StringBuilder'." diff --git a/csharp/ql/src/Performance/UseTryGetValue.ql b/csharp/ql/src/Performance/UseTryGetValue.ql index 074cb2a7ed6..c7e12bc1eaa 100644 --- a/csharp/ql/src/Performance/UseTryGetValue.ql +++ b/csharp/ql/src/Performance/UseTryGetValue.ql @@ -13,20 +13,16 @@ import csharp import semmle.code.csharp.commons.StructuralComparison import semmle.code.csharp.controlflow.Guards as G -class SameElement extends StructuralComparisonConfiguration -{ +class SameElement extends StructuralComparisonConfiguration { SameElement() { this = "Same element" } - override predicate candidate(Element e1, Element e2) - { + override predicate candidate(Element e1, Element e2) { exists(MethodCall mc, IndexerRead access | - mc.getTarget().hasName("ContainsKey") - and - access.getQualifier().(G::GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _) - and - e1 = mc.getArgument(0) - and - e2 = access.getIndex(0)) + mc.getTarget().hasName("ContainsKey") and + access.getQualifier().(G::GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _) and + e1 = mc.getArgument(0) and + e2 = access.getIndex(0) + ) } } diff --git a/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql b/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql index d04c3c3ac4d..447306e4522 100644 --- a/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql +++ b/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql @@ -16,7 +16,7 @@ import csharp import semmle.code.asp.WebConfig from SystemWebXMLElement web, XMLAttribute debugAttribute -where debugAttribute = web.getAChild("compilation").getAttribute("debug") - and not debugAttribute.getValue().toLowerCase() = "false" +where + debugAttribute = web.getAChild("compilation").getAttribute("debug") and + not debugAttribute.getValue().toLowerCase() = "false" select debugAttribute, "The 'debug' flag is set for an ASP.NET configuration file." - diff --git a/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql b/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql index d08cc2ca564..f25dd129f0c 100644 --- a/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql +++ b/csharp/ql/src/Security Features/CWE-022/TaintedPath.ql @@ -12,11 +12,12 @@ * external/cwe/cwe-073 * external/cwe/cwe-099 */ + import csharp import semmle.code.csharp.security.dataflow.TaintedPath::TaintedPath import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in a path.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a path.", source.getNode(), + "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql b/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql index fc687c1d6b2..0945c565881 100644 --- a/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql +++ b/csharp/ql/src/Security Features/CWE-022/ZipSlip.ql @@ -18,4 +18,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration zipTaintTracking, DataFlow::PathNode source, DataFlow::PathNode sink where zipTaintTracking.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", source.getNode(), "item path" + "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", + source.getNode(), "item path" diff --git a/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql b/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql index 337d191eae1..ece6dc5a0db 100644 --- a/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql +++ b/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql @@ -18,5 +18,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in a command.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a command.", source.getNode(), + "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql b/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql index be51a9e347e..b7a3c724d02 100644 --- a/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql +++ b/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql @@ -18,12 +18,10 @@ import semmle.code.csharp.security.dataflow.CommandInjection::CommandInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { - override predicate isSource(DataFlow::Node source) { - source instanceof StoredFlowSource - } + override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } } from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in a command.", source.getNode(), "Stored user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a command.", source.getNode(), + "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql b/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql index 80f16f35d4a..ebba14147ed 100644 --- a/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql +++ b/csharp/ql/src/Security Features/CWE-079/StoredXSS.ql @@ -10,22 +10,24 @@ * external/cwe/cwe-079 * external/cwe/cwe-116 */ + import csharp import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.XSS::XSS import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { - override predicate isSource(DataFlow::Node source) { - source instanceof StoredFlowSource - } + override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } } -from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink, string explanation -where c.hasFlowPath(source, sink) -and +from + StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink, + string explanation +where + c.hasFlowPath(source, sink) and if exists(sink.getNode().(Sink).explanation()) then explanation = ": " + sink.getNode().(Sink).explanation() + "." else explanation = "." select sink.getNode(), source, sink, - "$@ flows to here and is written to HTML or JavaScript" + explanation, source.getNode(), "Stored user-provided value" + "$@ flows to here and is written to HTML or JavaScript" + explanation, source.getNode(), + "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-079/XSS.ql b/csharp/ql/src/Security Features/CWE-079/XSS.ql index 5759722005a..2e07352708b 100644 --- a/csharp/ql/src/Security Features/CWE-079/XSS.ql +++ b/csharp/ql/src/Security Features/CWE-079/XSS.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-079 * external/cwe/cwe-116 */ + import csharp import semmle.code.csharp.security.dataflow.XSS::XSS diff --git a/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql b/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql index 3e533dfd993..d13702cc9ad 100644 --- a/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql +++ b/csharp/ql/src/Security Features/CWE-089/SecondOrderSqlInjection.ql @@ -16,12 +16,10 @@ import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends SqlInjection::TaintTrackingConfiguration { - override predicate isSource(DataFlow::Node source) { - source instanceof StoredFlowSource - } + override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } } from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in an SQL query.", source.getNode(), "Stored user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in an SQL query.", + source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql b/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql index f06eab7ef37..7a7f267c4ed 100644 --- a/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql +++ b/csharp/ql/src/Security Features/CWE-089/SqlInjection.ql @@ -1,14 +1,14 @@ /** -* @name SQL query built from user-controlled sources -* @description Building a SQL query from user-controlled sources is vulnerable to insertion of -* malicious SQL code by the user. -* @kind path-problem -* @problem.severity error -* @precision high -* @id cs/sql-injection -* @tags security -* external/cwe/cwe-089 -*/ + * @name SQL query built from user-controlled sources + * @description Building a SQL query from user-controlled sources is vulnerable to insertion of + * malicious SQL code by the user. + * @kind path-problem + * @problem.severity error + * @precision high + * @id cs/sql-injection + * @tags security + * external/cwe/cwe-089 + */ import csharp import semmle.code.csharp.security.dataflow.SqlInjection::SqlInjection @@ -16,5 +16,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "Query might include code from $@.", source, ("this " + source.getNode().(RemoteFlowSource).getSourceType()) +select sink.getNode(), source, sink, "Query might include code from $@.", source, + ("this " + source.getNode().(RemoteFlowSource).getSourceType()) diff --git a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql index 669e82e1d7e..cbe927fd7dd 100644 --- a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql +++ b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.ql @@ -9,11 +9,12 @@ * @tags security * external/cwe/cwe-090 */ + import csharp import semmle.code.csharp.security.dataflow.LDAPInjection::LDAPInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in an LDAP query.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in an LDAP query.", + source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql b/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql index 846ad8735ac..2618ab3f146 100644 --- a/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql +++ b/csharp/ql/src/Security Features/CWE-090/StoredLDAPInjection.ql @@ -9,18 +9,17 @@ * @tags security * external/cwe/cwe-090 */ + import csharp import semmle.code.csharp.security.dataflow.LDAPInjection::LDAPInjection import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { - override predicate isSource(DataFlow::Node source) { - source instanceof StoredFlowSource - } + override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } } from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in an LDAP query.", source.getNode(), "Stored user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in an LDAP query.", + source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql b/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql index de26ec087e1..486328bdf3c 100644 --- a/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql +++ b/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql @@ -11,11 +11,12 @@ * external/cwe/cwe-095 * external/cwe/cwe-096 */ + import csharp import semmle.code.csharp.security.dataflow.CodeInjection::CodeInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is compiled as code.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is compiled as code.", source.getNode(), + "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql b/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql index 50b3bc2c45f..d6960ef735e 100644 --- a/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql +++ b/csharp/ql/src/Security Features/CWE-099/ResourceInjection.ql @@ -9,11 +9,12 @@ * @tags security * external/cwe/cwe-099 */ + import csharp import semmle.code.csharp.security.dataflow.ResourceInjection::ResourceInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in a resource descriptor.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a resource descriptor.", + source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql b/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql index e2c051f260e..ab629d1f4d5 100644 --- a/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql +++ b/csharp/ql/src/Security Features/CWE-112/MissingXMLValidation.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-112 */ + import csharp import semmle.code.csharp.security.dataflow.MissingXMLValidation::MissingXMLValidation import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -16,4 +17,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "$@ flows to here and is processed as XML without validation because " + sink.getNode().(Sink).getReason(), source.getNode(), "User-provided value" + "$@ flows to here and is processed as XML without validation because " + + sink.getNode().(Sink).getReason(), source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-117/LogForging.ql b/csharp/ql/src/Security Features/CWE-117/LogForging.ql index 010a46f0650..400beef0daf 100644 --- a/csharp/ql/src/Security Features/CWE-117/LogForging.ql +++ b/csharp/ql/src/Security Features/CWE-117/LogForging.ql @@ -9,11 +9,12 @@ * @tags security * external/cwe/cwe-117 */ + import csharp import semmle.code.csharp.security.dataflow.LogForging::LogForging import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to log entry.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to log entry.", source.getNode(), + "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql b/csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql index 411a683cb77..9dca3ce9781 100644 --- a/csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql +++ b/csharp/ql/src/Security Features/CWE-119/LocalUnvalidatedArithmetic.ql @@ -13,6 +13,7 @@ * external/cwe/cwe-122 * external/cwe/cwe-788 */ + import csharp import semmle.code.csharp.controlflow.Guards @@ -24,8 +25,10 @@ where DataFlow::localFlow(DataFlow::exprNode(taintSrc), DataFlow::exprNode(add.getAnOperand())) and // virtual method call result has not been validated not exists(Expr check, ComparisonOperation cmp | - DataFlow::localFlow(DataFlow::exprNode(taintSrc), DataFlow::exprNode(check)) | + DataFlow::localFlow(DataFlow::exprNode(taintSrc), DataFlow::exprNode(check)) + | cmp.getAnOperand() = check and add.getAnOperand().(GuardedExpr).isGuardedBy(cmp, check, _) ) -select add, "Unvalidated pointer arithmetic from virtual method $@.", taintSrc, taintSrc.getTarget().getName() +select add, "Unvalidated pointer arithmetic from virtual method $@.", taintSrc, + taintSrc.getTarget().getName() diff --git a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql index 13377c0e39d..4419a4f1312 100644 --- a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql +++ b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql @@ -18,9 +18,7 @@ import semmle.code.csharp.frameworks.System import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "Exposure through transmitted data" - } + TaintTrackingConfiguration() { this = "Exposure through transmitted data" } override predicate isSource(DataFlow::Node source) { // `source` may contain a password @@ -30,17 +28,18 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { exists(PropertyRead pr, Property prop | source.asExpr() = pr and pr.getQualifier().getType() = any(SystemDataCommon::DbException de).getASubType*() and - prop = pr.getTarget() | + prop = pr.getTarget() + | prop.getName() = "Message" or prop.getName() = "Data" - ) + ) or // `source` is from `DbException.ToString()` exists(MethodCall mc | source.asExpr() = mc and mc.getQualifier().getType() = any(SystemDataCommon::DbException de).getASubType*() and mc.getTarget() = any(SystemObjectClass c).getToStringMethod().getAnOverrider*() - ) + ) } override predicate isSink(DataFlow::Node sink) { @@ -53,4 +52,5 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink where configuration.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "Sensitive information from $@ flows to here, and is transmitted to the user.", source.getNode(), source.toString() + "Sensitive information from $@ flows to here, and is transmitted to the user.", source.getNode(), + source.toString() diff --git a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql index 92e0a2c2905..d2ad68f9d61 100644 --- a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql +++ b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql @@ -21,37 +21,35 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph * A taint-tracking configuration for reasoning about stack traces that flow to web page outputs. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "StackTrace" - } + TaintTrackingConfiguration() { this = "StackTrace" } - override - predicate isSource(DataFlow::Node source) { + override predicate isSource(DataFlow::Node source) { exists(Expr exceptionExpr | // Writing an exception directly is bad - source.asExpr() = exceptionExpr or + source.asExpr() = exceptionExpr + or // Writing an exception property is bad - source.asExpr().(PropertyAccess).getQualifier() = exceptionExpr or + source.asExpr().(PropertyAccess).getQualifier() = exceptionExpr + or // Writing the result of ToString is bad - source.asExpr() = any(MethodCall mc | mc.getQualifier() = exceptionExpr and mc.getTarget().hasName("ToString")) - | + source.asExpr() = any(MethodCall mc | + mc.getQualifier() = exceptionExpr and mc.getTarget().hasName("ToString") + ) + | // Expr has type `System.Exception`. exceptionExpr.getType().(RefType).getABaseType*() instanceof SystemExceptionClass and // And is not within an exception callable. not exists(Callable enclosingCallable | - enclosingCallable = exceptionExpr.getEnclosingCallable() | + enclosingCallable = exceptionExpr.getEnclosingCallable() + | enclosingCallable.getDeclaringType().getABaseType*() instanceof SystemExceptionClass ) ) } - override - predicate isSink(DataFlow::Node sink) { - sink instanceof XSS::Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof XSS::Sink } - override - predicate isSanitizer(DataFlow::Node sanitizer) { + override predicate isSanitizer(DataFlow::Node sanitizer) { // Do not flow through Message sanitizer.asExpr() = any(SystemExceptionClass se).getProperty("Message").getAnAccess() } @@ -60,4 +58,5 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "Exception information from $@ flows to here, and is exposed to the user.", source.getNode(), source.toString() + "Exception information from $@ flows to here, and is exposed to the user.", source.getNode(), + source.toString() diff --git a/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql b/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql index a514fc51915..0cf979ad3d6 100644 --- a/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql +++ b/csharp/ql/src/Security Features/CWE-248/MissingASPNETGlobalErrorHandler.ql @@ -24,8 +24,10 @@ class Application_Error extends Method { } from CustomErrorsXMLElement customError - // `` must be set to "off" to be dangerous -where customError.getAttributeValue("mode").toLowerCase() = "off" - // There must not be an error handler in global.asax - and not exists(Application_Error ae) -select customError, "'customErrors' mode set to off in Web.config, and no 'Application_Error' handler specified in the global.asax file." +// `` must be set to "off" to be dangerous +where + customError.getAttributeValue("mode").toLowerCase() = "off" and + // There must not be an error handler in global.asax + not exists(Application_Error ae) +select customError, + "'customErrors' mode set to off in Web.config, and no 'Application_Error' handler specified in the global.asax file." diff --git a/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql b/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql index 86a40318b83..44209db60cb 100644 --- a/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql +++ b/csharp/ql/src/Security Features/CWE-312/CleartextStorage.ql @@ -11,11 +11,12 @@ * external/cwe/cwe-315 * external/cwe/cwe-359 */ + import csharp import semmle.code.csharp.security.dataflow.CleartextStorage::CleartextStorage import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "Sensitive data returned by $@ is stored here.", source.getNode(), source.toString() +select sink.getNode(), source, sink, "Sensitive data returned by $@ is stored here.", + source.getNode(), source.toString() diff --git a/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql b/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql index 3a4293fddac..dc32755c6b1 100644 --- a/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql +++ b/csharp/ql/src/Security Features/CWE-327/DontInstallRootCert.ql @@ -8,6 +8,7 @@ * @tags security * external/cwe/cwe-327 */ + import csharp import semmle.code.csharp.dataflow.DataFlow::DataFlow import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -17,22 +18,29 @@ class AddCertToRootStoreConfig extends DataFlow::Configuration { override predicate isSource(DataFlow::Node source) { exists(ObjectCreation oc | oc = source.asExpr() | - oc.getType().(RefType).hasQualifiedName("System.Security.Cryptography.X509Certificates.X509Store") and + oc + .getType() + .(RefType) + .hasQualifiedName("System.Security.Cryptography.X509Certificates.X509Store") and oc.getArgument(0).(Access).getTarget().hasName("Root") ) } override predicate isSink(DataFlow::Node sink) { exists(MethodCall mc | - (mc.getTarget().hasQualifiedName("System.Security.Cryptography.X509Certificates.X509Store", "Add") or - mc.getTarget().hasQualifiedName("System.Security.Cryptography.X509Certificates.X509Store", "AddRange")) and - sink.asExpr() = mc.getQualifier() + ( + mc + .getTarget() + .hasQualifiedName("System.Security.Cryptography.X509Certificates.X509Store", "Add") or + mc + .getTarget() + .hasQualifiedName("System.Security.Cryptography.X509Certificates.X509Store", "AddRange") + ) and + sink.asExpr() = mc.getQualifier() ) } } from DataFlow::PathNode oc, DataFlow::PathNode mc, AddCertToRootStoreConfig config where config.hasFlowPath(oc, mc) -select mc.getNode(), oc, mc, - "Certificate added to the root certificate store." - +select mc.getNode(), oc, mc, "Certificate added to the root certificate store." diff --git a/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql b/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql index 043858b4637..245d8f50b01 100644 --- a/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql +++ b/csharp/ql/src/Security Features/CWE-352/MissingAntiForgeryTokenValidation.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-352 */ + import csharp import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.Helpers @@ -28,27 +29,34 @@ predicate hasGlobalAntiForgeryFilter() { /* * A global filter added */ + exists(MethodCall addGlobalFilter | // addGlobalFilter adds a filter to the global filter collection addGlobalFilter.getTarget() = any(GlobalFilterCollection gfc).getAddMethod() and // The filter is an antiforgery filter addGlobalFilter.getArgumentForName("filter").getType() instanceof AntiForgeryAuthorizationFilter and // The filter is added by the Application_Start() method - any(WebApplication wa).getApplication_StartMethod().calls*(addGlobalFilter.getEnclosingCallable()) + any(WebApplication wa) + .getApplication_StartMethod() + .calls*(addGlobalFilter.getEnclosingCallable()) ) } from Controller c, Method postMethod -where postMethod = c.getAPostActionMethod() +where + postMethod = c.getAPostActionMethod() and // The method is not protected by a validate anti forgery token attribute - and not postMethod.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute - and not c.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute + not postMethod.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute and + not c.getAnAttribute() instanceof ValidateAntiForgeryTokenAttribute and /* * Verify that validate anti forgery token attributes are used somewhere within this project, to * avoid reporting false positives on projects that use an alternative approach to mitigate CSRF * issues. */ - and exists(ValidateAntiForgeryTokenAttribute a, Element e | e = a.getTarget()) + + exists(ValidateAntiForgeryTokenAttribute a, Element e | e = a.getTarget()) and // Also ignore cases where a global anti forgery filter is in use. - and not hasGlobalAntiForgeryFilter() -select postMethod, "Method '" + postMethod.getName() + "' handles a POST request without performing CSRF token validation." + not hasGlobalAntiForgeryFilter() +select postMethod, + "Method '" + postMethod.getName() + + "' handles a POST request without performing CSRF token validation." diff --git a/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql b/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql index 9f952f4db50..7f765d7c0aa 100644 --- a/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql +++ b/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-359 */ + import csharp import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformation::ExposureOfPrivateInformation import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -16,4 +17,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "Private data returned by $@ is written to an external location.", source.getNode(), source.getNode().toString() + "Private data returned by $@ is written to an external location.", source.getNode(), + source.getNode().toString() diff --git a/csharp/ql/src/Security Features/CWE-384/AbandonSession.ql b/csharp/ql/src/Security Features/CWE-384/AbandonSession.ql index d766f926c1a..c9a397c02c6 100644 --- a/csharp/ql/src/Security Features/CWE-384/AbandonSession.ql +++ b/csharp/ql/src/Security Features/CWE-384/AbandonSession.ql @@ -14,19 +14,16 @@ import csharp import semmle.code.csharp.frameworks.system.web.Security -predicate loginMethod(Method m, ControlFlow::SuccessorType flowFrom) -{ - ( - m = any(SystemWebSecurityMembershipClass c).getValidateUserMethod() - or - m = any(SystemWebSecurityFormsAuthenticationClass c).getAuthenticateMethod() - ) - and - flowFrom.(ControlFlow::SuccessorTypes::BooleanSuccessor).getValue()=true +predicate loginMethod(Method m, ControlFlow::SuccessorType flowFrom) { + ( + m = any(SystemWebSecurityMembershipClass c).getValidateUserMethod() + or + m = any(SystemWebSecurityFormsAuthenticationClass c).getAuthenticateMethod() + ) and + flowFrom.(ControlFlow::SuccessorTypes::BooleanSuccessor).getValue() = true or - m = any(SystemWebSecurityFormsAuthenticationClass c).getSignOutMethod() - and - flowFrom instanceof ControlFlow::SuccessorTypes::NormalSuccessor + m = any(SystemWebSecurityFormsAuthenticationClass c).getSignOutMethod() and + flowFrom instanceof ControlFlow::SuccessorTypes::NormalSuccessor } /** The `System.Web.SessionState.HttpSessionState` class. */ @@ -43,34 +40,33 @@ class SystemWebSessionStateHttpSessionStateClass extends Class { } /** A method that directly or indirectly clears `HttpSessionState`. */ -predicate sessionEndMethod(Method m) -{ +predicate sessionEndMethod(Method m) { exists(SystemWebSessionStateHttpSessionStateClass ss | - m=ss.getAbandonMethod() or m = ss.getClearMethod()) + m = ss.getAbandonMethod() or m = ss.getClearMethod() + ) or exists(Method r | m.calls(r) and sessionEndMethod(r)) - } /** A use of `HttpSessionState`, other than to clear it. */ -predicate sessionUse(MemberAccess ma) -{ - ma.getType() instanceof SystemWebSessionStateHttpSessionStateClass - and +predicate sessionUse(MemberAccess ma) { + ma.getType() instanceof SystemWebSessionStateHttpSessionStateClass and not exists(MethodCall end | end.getQualifier() = ma and sessionEndMethod(end.getTarget())) } /** A control flow step that is not sanitised by a call to clear the session. */ -predicate controlStep(ControlFlow::Node s1, ControlFlow::Node s2) -{ - s2 = s1.getASuccessor() - and +predicate controlStep(ControlFlow::Node s1, ControlFlow::Node s2) { + s2 = s1.getASuccessor() and not sessionEndMethod(s2.getElement().(MethodCall).getTarget()) } -from ControlFlow::Node loginCall, Method loginMethod, ControlFlow::Node sessionUse, ControlFlow::SuccessorType fromLoginFlow -where loginMethod = loginCall.getElement().(MethodCall).getTarget() - and loginMethod(loginMethod, fromLoginFlow) - and sessionUse(sessionUse.getElement()) - and controlStep+(loginCall.getASuccessorByType(fromLoginFlow), sessionUse) -select sessionUse, "This session has not been invalidated following the call to '$@'.", loginCall, loginMethod.getName() +from + ControlFlow::Node loginCall, Method loginMethod, ControlFlow::Node sessionUse, + ControlFlow::SuccessorType fromLoginFlow +where + loginMethod = loginCall.getElement().(MethodCall).getTarget() and + loginMethod(loginMethod, fromLoginFlow) and + sessionUse(sessionUse.getElement()) and + controlStep+(loginCall.getASuccessorByType(fromLoginFlow), sessionUse) +select sessionUse, "This session has not been invalidated following the call to '$@'.", loginCall, + loginMethod.getName() diff --git a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql index 2034acf90d5..010ba26a406 100644 --- a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql +++ b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql @@ -31,8 +31,15 @@ predicate hasWebConfigXFrameOptions() { * * ``` */ + exists(XMLElement element | - element = any(WebConfigXML webConfig).getARootElement().getAChild("system.webServer").getAChild("httpProtocol").getAChild("customHeaders").getAChild("add") | + element = any(WebConfigXML webConfig) + .getARootElement() + .getAChild("system.webServer") + .getAChild("httpProtocol") + .getAChild("customHeaders") + .getAChild("add") + | element.getAttributeValue("name") = "X-Frame-Options" ) } @@ -44,12 +51,14 @@ predicate hasWebConfigXFrameOptions() { predicate hasCodeXFrameOptions() { 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() = "X-Frame-Options" ) } from WebConfigXML webConfig -where not hasWebConfigXFrameOptions() - and not hasCodeXFrameOptions() +where + not hasWebConfigXFrameOptions() and + not hasCodeXFrameOptions() select webConfig, "Configuration file is missing the X-Frame-Options setting." diff --git a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql index e951bba312d..a3ece934561 100644 --- a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql +++ b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.ql @@ -9,11 +9,12 @@ * @tags security * external/cwe/cwe-601 */ + import csharp import semmle.code.csharp.security.dataflow.UrlRedirect::UrlRedirect import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "Untrusted URL redirection due to $@.", source.getNode(), "user-provided value" +select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source.getNode(), + "user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql b/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql index 6458534cbf4..9acb765252f 100644 --- a/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql +++ b/csharp/ql/src/Security Features/CWE-611/UntrustedDataInsecureXml.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-827 * external/cwe/cwe-776 */ + import csharp import semmle.code.csharp.security.dataflow.XMLEntityInjection::XMLEntityInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -17,4 +18,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "$@ flows to here and is loaded insecurely as XML (" + sink.getNode().(Sink).getReason() +").", source.getNode(), "User-provided value" + "$@ flows to here and is loaded insecurely as XML (" + sink.getNode().(Sink).getReason() + ").", + source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.ql b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.ql index cac3a84af6f..d1159a39f99 100644 --- a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.ql +++ b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.ql @@ -11,6 +11,7 @@ * external/cwe/cwe-827 * external/cwe/cwe-776 */ + import csharp import semmle.code.csharp.security.xml.InsecureXML::InsecureXML diff --git a/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql b/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql index f6da2540390..0cfd4868c29 100644 --- a/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql +++ b/csharp/ql/src/Security Features/CWE-614/RequireSSL.ql @@ -17,43 +17,34 @@ import semmle.code.asp.WebConfig import semmle.code.csharp.frameworks.system.Web class FormsElement extends XMLElement { - FormsElement() { this = any(SystemWebXMLElement sw).getAChild("authentication").getAChild("forms") } - string getRequireSSL() { - result = getAttribute("requireSSL").getValue().trim().toLowerCase() - } + string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() } - predicate isRequireSSL() { - getRequireSSL() = "true" - } + predicate isRequireSSL() { getRequireSSL() = "true" } } class HttpCookiesElement extends XMLElement { - HttpCookiesElement() { - this = any(SystemWebXMLElement sw).getAChild("httpCookies") - } + HttpCookiesElement() { this = any(SystemWebXMLElement sw).getAChild("httpCookies") } - string getRequireSSL() { - result = getAttribute("requireSSL").getValue().trim().toLowerCase() - } + string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() } predicate isRequireSSL() { getRequireSSL() = "true" or - not getRequireSSL() = "false" - and exists(FormsElement forms | forms.getFile() = getFile() | forms.isRequireSSL()) + not getRequireSSL() = "false" and + exists(FormsElement forms | forms.getFile() = getFile() | forms.isRequireSSL()) } } from XMLElement element where - element instanceof FormsElement and - not element.(FormsElement).isRequireSSL() + element instanceof FormsElement and + not element.(FormsElement).isRequireSSL() or - element instanceof HttpCookiesElement - and not element.(HttpCookiesElement).isRequireSSL() - and not any(SystemWebHttpCookie c).getSecureProperty().getAnAssignedValue().getValue() = "true" + element instanceof HttpCookiesElement and + not element.(HttpCookiesElement).isRequireSSL() and + not any(SystemWebHttpCookie c).getSecureProperty().getAnAssignedValue().getValue() = "true" select element, "The 'requireSSL' attribute is not set to 'true'." diff --git a/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql b/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql index 3734533d9f0..5078afd9b33 100644 --- a/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql +++ b/csharp/ql/src/Security Features/CWE-643/StoredXPathInjection.ql @@ -9,19 +9,17 @@ * @tags security * external/cwe/cwe-643 */ + import csharp import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.XPathInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph class StoredTaintTrackingConfiguration extends XPathInjection::TaintTrackingConfiguration { - override - predicate isSource(DataFlow::Node source) { - source instanceof StoredFlowSource - } + override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } } from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in an XPath expression.", source.getNode(), "Stored user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.", + source.getNode(), "Stored user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql b/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql index e5eba0b9db4..5506ef6b637 100644 --- a/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql +++ b/csharp/ql/src/Security Features/CWE-643/XPathInjection.ql @@ -9,11 +9,12 @@ * @tags security * external/cwe/cwe-643 */ + import csharp import semmle.code.csharp.security.dataflow.XPathInjection::XPathInjection import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to here and is used in an XPath expression.", source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.", + source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-730/ReDoS.ql b/csharp/ql/src/Security Features/CWE-730/ReDoS.ql index 83aab48820e..94db79a0693 100644 --- a/csharp/ql/src/Security Features/CWE-730/ReDoS.ql +++ b/csharp/ql/src/Security Features/CWE-730/ReDoS.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-730 * external/cwe/cwe-400 */ + import csharp import semmle.code.csharp.security.dataflow.ReDoS::ReDoS import semmle.code.csharp.frameworks.system.text.RegularExpressions @@ -26,4 +27,5 @@ where sink.getNode() instanceof ExponentialRegexSink ) select sink.getNode(), source, sink, - "$@ flows to regular expression operation with dangerous regex.", source.getNode(), "User-provided value" + "$@ flows to regular expression operation with dangerous regex.", source.getNode(), + "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql b/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql index 2582acc7ebe..ad0974235e9 100644 --- a/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql +++ b/csharp/ql/src/Security Features/CWE-730/RegexInjection.ql @@ -11,14 +11,16 @@ * external/cwe/cwe-730 * external/cwe/cwe-400 */ + import csharp import semmle.code.csharp.security.dataflow.RegexInjection::RegexInjection import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink -where c.hasFlowPath(source, sink) +where + c.hasFlowPath(source, sink) and // No global timeout set - and not exists(RegexGlobalTimeout r) -select sink.getNode(), source, sink, - "$@ flows to the construction of a regular expression.", source.getNode(), "User-provided value" + not exists(RegexGlobalTimeout r) +select sink.getNode(), source, sink, "$@ flows to the construction of a regular expression.", + source.getNode(), "User-provided value" diff --git a/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql b/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql index 481268366cb..a760a9034cd 100644 --- a/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql +++ b/csharp/ql/src/Security Features/CWE-798/HardcodedConnectionString.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-321 * external/cwe/cwe-798 */ + import csharp import semmle.code.csharp.frameworks.system.Data import semmle.code.csharp.security.dataflow.HardcodedCredentials @@ -28,27 +29,25 @@ class ConnectionStringPasswordOrUsername extends HardcodedCredentials::NonEmptyS * A taint-tracking configuration for tracking string literals to a `ConnectionString` property. */ class ConnectionStringTaintTrackingConfiguration extends TaintTracking::Configuration { - ConnectionStringTaintTrackingConfiguration() { - this = "connectionstring" + ConnectionStringTaintTrackingConfiguration() { this = "connectionstring" } + + override predicate isSource(DataFlow::Node source) { + source instanceof ConnectionStringPasswordOrUsername } - override - predicate isSource(DataFlow::Node source) { - source instanceof ConnectionStringPasswordOrUsername + override predicate isSink(DataFlow::Node sink) { + sink.asExpr() = any(SystemDataConnectionClass connection) + .getConnectionStringProperty() + .getAnAssignedValue() } - override - predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(SystemDataConnectionClass connection).getConnectionStringProperty().getAnAssignedValue() - } - - override - predicate isSanitizer(DataFlow::Node node) { + override predicate isSanitizer(DataFlow::Node node) { node instanceof HardcodedCredentials::StringFormatSanitizer } } -from ConnectionStringTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink +from + ConnectionStringTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) select source.getNode(), source, sink, "'ConnectionString' property includes hard-coded credentials set in $@.", diff --git a/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql b/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql index 11d4307d05e..638c96003dd 100644 --- a/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql +++ b/csharp/ql/src/Security Features/CWE-798/HardcodedCredentials.ql @@ -10,22 +10,21 @@ * external/cwe/cwe-321 * external/cwe/cwe-798 */ + import csharp import semmle.code.csharp.security.dataflow.HardcodedCredentials::HardcodedCredentials import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph -from TaintTrackingConfiguration c, Source source, Sink sink, DataFlow::PathNode sourcePath, DataFlow::PathNode sinkPath, - string value +from + TaintTrackingConfiguration c, Source source, Sink sink, DataFlow::PathNode sourcePath, + DataFlow::PathNode sinkPath, string value where source = sourcePath.getNode() and sink = sinkPath.getNode() and c.hasFlow(source, sink) and // Print the source value if it's available - if exists(source.asExpr().getValue()) then - value = "The hard-coded value \"" + source.asExpr().getValue() + "\"" - else - value = "This hard-coded value" -select source, sourcePath, sinkPath, - value + " flows to " + sink.getSinkDescription() + ".", - sink, sink.getSinkName(), sink.getSupplementaryElement(), - sink.getSupplementaryElement().toString() + if exists(source.asExpr().getValue()) + then value = "The hard-coded value \"" + source.asExpr().getValue() + "\"" + else value = "This hard-coded value" +select source, sourcePath, sinkPath, value + " flows to " + sink.getSinkDescription() + ".", sink, + sink.getSinkName(), sink.getSupplementaryElement(), sink.getSupplementaryElement().toString() diff --git a/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql b/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql index cf16ee88306..e3ba8463b76 100644 --- a/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql +++ b/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql @@ -11,6 +11,7 @@ * external/cwe/cwe-247 * external/cwe/cwe-350 */ + import csharp import semmle.code.csharp.security.dataflow.ConditionalBypass::UserControlledBypassOfSensitiveMethod import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -18,5 +19,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select sink.getNode().(Sink).getSensitiveMethodCall(), source, sink, - "Sensitive method may not be executed depending on $@, which flows from $@.", - sink.getNode(), "this condition", source.getNode(), "user input" + "Sensitive method may not be executed depending on $@, which flows from $@.", sink.getNode(), + "this condition", source.getNode(), "user input" diff --git a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql index 133f1f3b3b2..ef9b433cd94 100644 --- a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql +++ b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql @@ -1,14 +1,14 @@ /** -* @name Inappropriate encoding -* @description Using an inappropriate encoding may give unintended results and may -* pose a security risk. -* @kind path-problem -* @problem.severity error -* @precision low -* @id cs/inappropriate-encoding -* @tags security -* external/cwe/cwe-838 -*/ + * @name Inappropriate encoding + * @description Using an inappropriate encoding may give unintended results and may + * pose a security risk. + * @kind path-problem + * @problem.severity error + * @precision low + * @id cs/inappropriate-encoding + * @tags security + * external/cwe/cwe-838 + */ import csharp import DataFlow @@ -52,20 +52,15 @@ abstract class RequiresEncodingConfiguration extends TaintTracking::Configuratio override predicate isSource(Node source) { // all encoded values that do not match this configuration are // considered sources - exists(Expr e | - e = source.asExpr() | + exists(Expr e | e = source.asExpr() | e instanceof EncodedValue and not this.isPossibleEncodedValue(e) ) } - override predicate isSink(Node sink) { - this.requiresEncoding(sink) - } + override predicate isSink(Node sink) { this.requiresEncoding(sink) } - override predicate isSanitizer(Node sanitizer) { - this.isPossibleEncodedValue(sanitizer.asExpr()) - } + override predicate isSanitizer(Node sanitizer) { this.isPossibleEncodedValue(sanitizer.asExpr()) } } /** An encoded value, for example a call to `HttpServerUtility.HtmlEncode`. */ @@ -89,72 +84,50 @@ class EncodedValue extends Expr { module EncodingConfigurations { /** An encoding configuration for SQL expressions. */ class SqlExpr extends RequiresEncodingConfiguration { - SqlExpr() { - this = "SqlExpr" - } + SqlExpr() { this = "SqlExpr" } - override string getKind() { - result = "SQL expression" - } + override string getKind() { result = "SQL expression" } - override predicate requiresEncoding(Node n) { - n instanceof SqlInjection::Sink - } + override predicate requiresEncoding(Node n) { n instanceof SqlInjection::Sink } // no override for `isPossibleEncodedValue` as SQL parameters should // be used instead of explicit encoding - override predicate isSource(Node source) { - super.isSource(source) or + super.isSource(source) + or // consider quote-replacing calls as additional sources for // SQL expressions (e.g., `s.Replace("\"", "\"\"")`) source.asExpr() = any(MethodCall mc | - mc.getTarget() = any(SystemStringClass c).getReplaceMethod() and - mc.getArgument(0).getValue().regexpMatch("\"|'|`") - ) + mc.getTarget() = any(SystemStringClass c).getReplaceMethod() and + mc.getArgument(0).getValue().regexpMatch("\"|'|`") + ) } } /** An encoding configuration for HTML expressions. */ class HtmlExpr extends RequiresEncodingConfiguration { - HtmlExpr() { - this = "HtmlExpr" - } + HtmlExpr() { this = "HtmlExpr" } - override string getKind() { - result = "HTML expression" - } + override string getKind() { result = "HTML expression" } - override predicate requiresEncoding(Node n) { - n instanceof XSS::HtmlSink - } + override predicate requiresEncoding(Node n) { n instanceof XSS::HtmlSink } - override predicate isPossibleEncodedValue(Expr e) { - e instanceof HtmlSanitizedExpr - } + override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr } } /** An encoding configuration for URL expressions. */ class UrlExpr extends RequiresEncodingConfiguration { - UrlExpr() { - this = "UrlExpr" - } + UrlExpr() { this = "UrlExpr" } - override string getKind() { - result = "URL expression" - } + override string getKind() { result = "URL expression" } - override predicate requiresEncoding(Node n) { - n instanceof UrlRedirect::Sink - } + override predicate requiresEncoding(Node n) { n instanceof UrlRedirect::Sink } - override predicate isPossibleEncodedValue(Expr e) { - e instanceof UrlSanitizedExpr - } + override predicate isPossibleEncodedValue(Expr e) { e instanceof UrlSanitizedExpr } } } from RequiresEncodingConfiguration c, PathNode encodedValue, PathNode sink, string kind where c.hasWrongEncoding(encodedValue, sink, kind) -select sink.getNode(), encodedValue, sink, - "This " + kind + " may include data from a $@.", encodedValue.getNode(), "possibly inappropriately encoded value" +select sink.getNode(), encodedValue, sink, "This " + kind + " may include data from a $@.", + encodedValue.getNode(), "possibly inappropriately encoded value" diff --git a/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql b/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql index 95631793507..4be7c76dd7b 100644 --- a/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql +++ b/csharp/ql/src/Security Features/CWE-937/VulnerablePackage.ql @@ -15,5 +15,6 @@ import Vulnerabilities from Vulnerability vuln, VulnerablePackage package where vuln = package.getVulnerability() -select package, "Package '" + package + "' has vulnerability $@, and should be upgraded to version " + package.getFixedVersion() + ".", - vuln.getUrl(), vuln.toString() +select package, + "Package '" + package + "' has vulnerability $@, and should be upgraded to version " + + package.getFixedVersion() + ".", vuln.getUrl(), vuln.toString() diff --git a/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql b/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql index b41900a13f7..f3cce1c36f5 100644 --- a/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql +++ b/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql @@ -8,11 +8,16 @@ * @tags security * external/cwe/cwe-287 */ + import csharp from Assignment a, PropertyAccess pa -where a.getLValue() = pa - and pa.getTarget().hasName("Domain") - and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpCookie") - and (a.getRValue().getValue().regexpReplaceAll("[^.]","").length() < 2 or a.getRValue().getValue().matches(".%")) +where + a.getLValue() = pa and + pa.getTarget().hasName("Domain") and + pa.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpCookie") and + ( + a.getRValue().getValue().regexpReplaceAll("[^.]", "").length() < 2 or + a.getRValue().getValue().matches(".%") + ) select a, "Overly broad domain for cookie." diff --git a/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql b/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql index 72f9514cf56..a75b41794dd 100644 --- a/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql +++ b/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql @@ -8,11 +8,13 @@ * @tags security * external/cwe/cwe-287 */ + import csharp from Assignment a, PropertyAccess pa -where a.getLValue() = pa - and pa.getTarget().hasName("Path") - and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpCookie") - and a.getRValue().getValue() = "/" +where + a.getLValue() = pa and + pa.getTarget().hasName("Path") and + pa.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpCookie") and + a.getRValue().getValue() = "/" select a, "Overly broad path for cookie." diff --git a/csharp/ql/src/Security Features/Encryption using ECB.ql b/csharp/ql/src/Security Features/Encryption using ECB.ql index 2146eddb34b..2d36bd99306 100644 --- a/csharp/ql/src/Security Features/Encryption using ECB.ql +++ b/csharp/ql/src/Security Features/Encryption using ECB.ql @@ -8,11 +8,13 @@ * @tags security * external/cwe/cwe-327 */ + import csharp from FieldAccess a, Field ecb, Enum e -where a.getTarget() = ecb - and ecb.hasName("ECB") - and ecb.getDeclaringType() = e - and e.hasQualifiedName("System.Security.Cryptography", "CipherMode") +where + a.getTarget() = ecb and + ecb.hasName("ECB") and + ecb.getDeclaringType() = e and + e.hasQualifiedName("System.Security.Cryptography", "CipherMode") select a, "The ECB (Electronic Code Book) encryption mode is vulnerable to replay attacks." diff --git a/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql b/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql index 05976c8becf..4a0fc38e8ab 100644 --- a/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql +++ b/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql @@ -8,20 +8,28 @@ * @tags security * external/cwe/cwe-113 */ + import csharp import semmle.code.asp.WebConfig from Element l -where // header checking is disabled programmatically in the code - exists(Assignment a, PropertyAccess pa | - a.getLValue() = pa - and pa.getTarget().hasName("EnableHeaderChecking") - and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.Configuration", "HttpRuntimeSection") - and a.getRValue().getValue() = "false" - and a = l) - or // header checking is disabled in a configuration file - exists(HttpRuntimeXMLElement e, XMLAttribute a | - a = e.getAttribute("enableHeaderChecking") - and a.getValue().toLowerCase() = "false" - and a = l) +where + // header checking is disabled programmatically in the code + exists(Assignment a, PropertyAccess pa | + a.getLValue() = pa and + pa.getTarget().hasName("EnableHeaderChecking") and + pa + .getTarget() + .getDeclaringType() + .hasQualifiedName("System.Web.Configuration", "HttpRuntimeSection") and + a.getRValue().getValue() = "false" and + a = l + ) + or + // header checking is disabled in a configuration file + exists(HttpRuntimeXMLElement e, XMLAttribute a | + a = e.getAttribute("enableHeaderChecking") and + a.getValue().toLowerCase() = "false" and + a = l + ) select l, "Do not disable header checking." diff --git a/csharp/ql/src/Security Features/InadequateRSAPadding.ql b/csharp/ql/src/Security Features/InadequateRSAPadding.ql index d2a72114c54..c24dddac775 100644 --- a/csharp/ql/src/Security Features/InadequateRSAPadding.ql +++ b/csharp/ql/src/Security Features/InadequateRSAPadding.ql @@ -9,11 +9,16 @@ * external/cwe/cwe-327 * external/cwe/cwe-780 */ + import csharp from MethodCall mc, BoolLiteral b -where mc.getTarget().hasName("Encrypt") - and mc.getTarget().getDeclaringType().hasQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") - and mc.getArgument(1) = b - and b.getValue() = "false" +where + mc.getTarget().hasName("Encrypt") and + mc + .getTarget() + .getDeclaringType() + .hasQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") and + mc.getArgument(1) = b and + b.getValue() = "false" select b, "Enable RSA padding." diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index 37dd0f1d481..e9c1822e54d 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -10,6 +10,7 @@ * @tags security * external/cwe/cwe-338 */ + import csharp import semmle.code.csharp.frameworks.Test import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -37,21 +38,13 @@ module Random { * A taint-tracking configuration for insecure randomness in security sensitive context. */ class TaintTrackingConfiguration extends TaintTracking::Configuration { - TaintTrackingConfiguration() { - this = "RandomDataFlowConfiguration" - } + TaintTrackingConfiguration() { this = "RandomDataFlowConfiguration" } - 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 isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { // succ = array_or_indexer[pred] - use of random numbers in an index @@ -62,7 +55,9 @@ module Random { /** A source of cryptographically insecure random numbers. */ class RandomSource extends Source { RandomSource() { - this.getExpr() = any(MethodCall mc | mc.getQualifier().getType().(RefType).hasQualifiedName("System", "Random")) + this.getExpr() = any(MethodCall mc | + mc.getQualifier().getType().(RefType).hasQualifiedName("System", "Random") + ) } } @@ -71,15 +66,20 @@ module Random { SensitiveSink() { exists(Expr e | // Simple assignment - e = this.getExpr() | - e = any(SensitiveVariable v).getAnAssignedValue() or - e = any(SensitiveProperty v).getAnAssignedValue() or - e = any(SensitiveLibraryParameter v).getAnAssignedArgument() or + e = this.getExpr() + | + e = any(SensitiveVariable v).getAnAssignedValue() + or + e = any(SensitiveProperty v).getAnAssignedValue() + or + e = any(SensitiveLibraryParameter v).getAnAssignedArgument() + or // Assignment operation, e.g. += or similar exists(AssignOperation ao | ao.getRValue() = e and // "expanded" assignments will be covered by simple assignment - not ao.hasExpandedAssignment() | + not ao.hasExpandedAssignment() + | ao.getLValue() = any(SensitiveVariable v).getAnAccess() or ao.getLValue() = any(SensitiveProperty v).getAnAccess() or ao.getLValue() = any(SensitiveLibraryParameter v).getAnAccess() @@ -94,8 +94,7 @@ module Random { */ class AlreadyTrackedSanitizer extends Sanitizer { AlreadyTrackedSanitizer() { - exists(Expr e | - e = this.getExpr() | + exists(Expr e | e = this.getExpr() | e = any(SensitiveVariable v).getAnAccess() or e = any(SensitiveProperty v).getAnAccess() or e = any(SensitiveLibraryParameter v).getAnAccess() @@ -104,7 +103,10 @@ module Random { } } -from Random::TaintTrackingConfiguration randomTracking, DataFlow::PathNode source, DataFlow::PathNode sink +from + Random::TaintTrackingConfiguration randomTracking, DataFlow::PathNode source, + DataFlow::PathNode sink where randomTracking.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "Cryptographically insecure random number is generated at $@ and used here in a security context.", source.getNode(), source.getNode().toString() + "Cryptographically insecure random number is generated at $@ and used here in a security context.", + source.getNode(), source.getNode().toString() diff --git a/csharp/ql/src/Security Features/InsufficientKeySize.ql b/csharp/ql/src/Security Features/InsufficientKeySize.ql index e6b6f9ec7df..08bdcfd6724 100644 --- a/csharp/ql/src/Security Features/InsufficientKeySize.ql +++ b/csharp/ql/src/Security Features/InsufficientKeySize.ql @@ -8,30 +8,43 @@ * @tags security * external/cwe/cwe-327 */ + import csharp predicate incorrectUseOfRC2(Assignment e, string msg) { - exists(PropertyAccess pa | pa.getParent() = e and + exists(PropertyAccess pa | + pa.getParent() = e and pa.getTarget().hasName("EffectiveKeySize") and - pa.getTarget().getDeclaringType().hasQualifiedName("System.Security.Cryptography", "RC2CryptoServiceProvider")) and + pa + .getTarget() + .getDeclaringType() + .hasQualifiedName("System.Security.Cryptography", "RC2CryptoServiceProvider") + ) and e.getRValue().getValue().toInt() < 128 and msg = "Key size should be at least 128 bits for RC2 encryption." } predicate incorrectUseOfDSA(ObjectCreation e, string msg) { - e.getTarget().getDeclaringType().hasQualifiedName("System.Security.Cryptography", "DSACryptoServiceProvider") and + e + .getTarget() + .getDeclaringType() + .hasQualifiedName("System.Security.Cryptography", "DSACryptoServiceProvider") and exists(Expr i | e.getArgument(0) = i and i.getValue().toInt() < 1024) and msg = "Key size should be at least 1024 bits for DSA encryption." } predicate incorrectUseOfRSA(ObjectCreation e, string msg) { - e.getTarget().getDeclaringType().hasQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") and + e + .getTarget() + .getDeclaringType() + .hasQualifiedName("System.Security.Cryptography", "RSACryptoServiceProvider") and exists(Expr i | e.getArgument(0) = i and i.getValue().toInt() < 1024) and msg = "Key size should be at least 1024 bits for RSA encryption." } from Expr e, string msg -where incorrectUseOfRC2(e, msg) - or incorrectUseOfDSA(e, msg) - or incorrectUseOfRSA(e, msg) -select e,msg +where + incorrectUseOfRC2(e, msg) or + incorrectUseOfDSA(e, msg) or + incorrectUseOfRSA(e, msg) +select e, msg diff --git a/csharp/ql/src/Security Features/PersistentCookie.ql b/csharp/ql/src/Security Features/PersistentCookie.ql index 121dcc9d80a..7305bdaf239 100644 --- a/csharp/ql/src/Security Features/PersistentCookie.ql +++ b/csharp/ql/src/Security Features/PersistentCookie.ql @@ -8,25 +8,39 @@ * @tags security * external/cwe/cwe-539 */ + import csharp class FutureDateExpr extends MethodCall { - FutureDateExpr() { - exists(PropertyAccess pa | pa = this.getQualifier() and - pa.getTarget().hasName("Now") and - pa.getTarget().getDeclaringType().hasQualifiedName("System", "DateTime")) and + exists(PropertyAccess pa | + pa = this.getQualifier() and + pa.getTarget().hasName("Now") and + pa.getTarget().getDeclaringType().hasQualifiedName("System", "DateTime") + ) and this.getTarget().getName().matches("Add%") } float getTimeInSecond() { - this.getTarget().hasName("AddTicks") and result = this.getArgument(0).getValue().toFloat() / 10000000 or - this.getTarget().hasName("AddMilliseconds") and result = this.getArgument(0).getValue().toFloat() / 1000 or - this.getTarget().hasName("AddSeconds") and result = this.getArgument(0).getValue().toFloat() or - this.getTarget().hasName("AddMinutes") and result = this.getArgument(0).getValue().toFloat() * 60 or - this.getTarget().hasName("AddHours") and result = this.getArgument(0).getValue().toFloat() * 60 * 60 or - this.getTarget().hasName("AddDays") and result = this.getArgument(0).getValue().toFloat() * 60 * 60 * 24 or - this.getTarget().hasName("AddMonths") and result = this.getArgument(0).getValue().toFloat() * 60 * 60 * 24 * 365.25 / 12 + this.getTarget().hasName("AddTicks") and + result = this.getArgument(0).getValue().toFloat() / 10000000 + or + this.getTarget().hasName("AddMilliseconds") and + result = this.getArgument(0).getValue().toFloat() / 1000 + or + this.getTarget().hasName("AddSeconds") and result = this.getArgument(0).getValue().toFloat() + or + this.getTarget().hasName("AddMinutes") and + result = this.getArgument(0).getValue().toFloat() * 60 + or + this.getTarget().hasName("AddHours") and + result = this.getArgument(0).getValue().toFloat() * 60 * 60 + or + this.getTarget().hasName("AddDays") and + result = this.getArgument(0).getValue().toFloat() * 60 * 60 * 24 + or + this.getTarget().hasName("AddMonths") and + result = this.getArgument(0).getValue().toFloat() * 60 * 60 * 24 * 365.25 / 12 } predicate timeIsNotClear() { @@ -35,11 +49,11 @@ class FutureDateExpr extends MethodCall { } } - from Assignment a, PropertyAccess pa, FutureDateExpr fde -where a.getLValue() = pa - and a.getRValue() = fde - and pa.getTarget().hasName("Expires") - and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpCookie") - and (fde.timeIsNotClear() or fde.getTimeInSecond() > 300) // 5 minutes max +where + a.getLValue() = pa and + a.getRValue() = fde and + pa.getTarget().hasName("Expires") and + pa.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpCookie") and + (fde.timeIsNotClear() or fde.getTimeInSecond() > 300) // 5 minutes max select a, "Avoid persistent cookies." diff --git a/csharp/ql/src/Security Features/WeakEncryption.ql b/csharp/ql/src/Security Features/WeakEncryption.ql index 115b075472e..a2c87b4d921 100644 --- a/csharp/ql/src/Security Features/WeakEncryption.ql +++ b/csharp/ql/src/Security Features/WeakEncryption.ql @@ -8,6 +8,7 @@ * @tags security * external/cwe/cwe-327 */ + import csharp predicate incorrectUseOfDES(ObjectCreation e, string msg) { @@ -16,11 +17,15 @@ predicate incorrectUseOfDES(ObjectCreation e, string msg) { } predicate incorrectUseOfTripleDES(ObjectCreation e, string msg) { - e.getType().(Class).hasQualifiedName("System.Security.Cryptography", "TripleDESCryptoServiceProvider") and + e + .getType() + .(Class) + .hasQualifiedName("System.Security.Cryptography", "TripleDESCryptoServiceProvider") and msg = "TripleDES encryption provides at most 112 bits of security. Switch to AesCryptoServiceProvider or RijndaelManaged instead." } from Expr e, string msg -where incorrectUseOfDES(e, msg) - or incorrectUseOfTripleDES(e, msg) -select e,msg +where + incorrectUseOfDES(e, msg) or + incorrectUseOfTripleDES(e, msg) +select e, msg diff --git a/csharp/ql/src/Stubs/MinimalStubsFromSource.ql b/csharp/ql/src/Stubs/MinimalStubsFromSource.ql index 47ce45e467d..116237d8f17 100644 --- a/csharp/ql/src/Stubs/MinimalStubsFromSource.ql +++ b/csharp/ql/src/Stubs/MinimalStubsFromSource.ql @@ -17,13 +17,14 @@ class UsedInSource extends GeneratedDeclaration { or this = any(Call c).getTarget() or - this = any(TypeMention tm).getType() + this = any(TypeMention tm).getType() or - exists(Virtualizable v | v.fromSource() | this = v.getImplementee() or this = v.getOverridee()) + exists(Virtualizable v | v.fromSource() | + this = v.getImplementee() or this = v.getOverridee() + ) or this = any(Attribute a).getType().getAConstructor() - ) - and + ) and this.fromLibrary() } } diff --git a/csharp/ql/src/Useless code/DefaultToString.ql b/csharp/ql/src/Useless code/DefaultToString.ql index 4ee55ee588a..0b4b1f4e599 100644 --- a/csharp/ql/src/Useless code/DefaultToString.ql +++ b/csharp/ql/src/Useless code/DefaultToString.ql @@ -9,6 +9,7 @@ * @tags reliability * maintainability */ + import csharp import semmle.code.csharp.commons.Strings import semmle.code.csharp.frameworks.System @@ -19,8 +20,7 @@ import semmle.code.csharp.frameworks.System */ predicate invokesToString(Expr e, ValueOrRefType t) { // Explicit invocation - exists(MethodCall mc | - mc.getQualifier() = e | + exists(MethodCall mc | mc.getQualifier() = e | mc.getTarget() instanceof ToStringMethod and t = mc.getQualifier().getType() ) @@ -33,7 +33,8 @@ predicate invokesToString(Expr e, ValueOrRefType t) { t = e.stripCasts().getType() and not t instanceof StringType and exists(AssignableDefinitions::ImplicitParameterDefinition def, Parameter p, ParameterRead pr | - e = p.getAnAssignedArgument() | + e = p.getAnAssignedArgument() + | def.getParameter() = p and pr = def.getAReachableRead() and pr.getAControlFlowNode().postDominates(p.getCallable().getEntryPoint()) and @@ -46,20 +47,17 @@ predicate invokesToString(Expr e, ValueOrRefType t) { * method from `System.Object` or `System.ValueType`. */ predicate alwaysDefaultToString(ValueOrRefType t) { - exists(ToStringMethod m | - t.hasMethod(m) | + exists(ToStringMethod m | t.hasMethod(m) | m.getDeclaringType() instanceof SystemObjectClass or m.getDeclaringType() instanceof SystemValueTypeClass - ) - and + ) and not exists(RefType overriding | overriding.getAMethod() instanceof ToStringMethod and overriding.getABaseType+() = t ) } -newtype TDefaultToStringType = - TDefaultToStringType0(ValueOrRefType t) { alwaysDefaultToString(t) } +newtype TDefaultToStringType = TDefaultToStringType0(ValueOrRefType t) { alwaysDefaultToString(t) } class DefaultToStringType extends TDefaultToStringType { ValueOrRefType t; @@ -73,19 +71,19 @@ class DefaultToStringType extends TDefaultToStringType { // A workaround for generating empty URLs for non-source locations, because qltest // does not support non-source locations string getURL() { - exists(Location l | - l = t.getLocation() | - if l instanceof SourceLocation then - exists(string path, int a, int b, int c, int d | - l.hasLocationInfo(path, a, b, c, d) | + exists(Location l | l = t.getLocation() | + if l instanceof SourceLocation + then + exists(string path, int a, int b, int c, int d | l.hasLocationInfo(path, a, b, c, d) | toUrl(path, a, b, c, d, result) ) - else - result = "" + else result = "" ) } } from Expr e, DefaultToStringType t where invokesToString(e, t.getType()) -select e, "Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing.", t, t.getType().getName() +select e, + "Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing.", + t, t.getType().getName() diff --git a/csharp/ql/src/Useless code/FutileConditional.ql b/csharp/ql/src/Useless code/FutileConditional.ql index 127ece6a6fd..aab02c76b83 100644 --- a/csharp/ql/src/Useless code/FutileConditional.ql +++ b/csharp/ql/src/Useless code/FutileConditional.ql @@ -8,20 +8,22 @@ * @tags reliability * readability */ + import csharp predicate emptyStmt(Stmt s) { s instanceof EmptyStmt or s = any(BlockStmt bs | - bs.getNumberOfStmts() = 0 - or - bs.getNumberOfStmts() = 1 and - emptyStmt(bs.getStmt(0)) - ) + bs.getNumberOfStmts() = 0 + or + bs.getNumberOfStmts() = 1 and + emptyStmt(bs.getStmt(0)) + ) } from IfStmt ifstmt -where emptyStmt(ifstmt.getThen()) - and (not exists(ifstmt.getElse()) or emptyStmt(ifstmt.getElse())) +where + emptyStmt(ifstmt.getThen()) and + (not exists(ifstmt.getElse()) or emptyStmt(ifstmt.getElse())) select ifstmt, "If-statement with an empty then-branch and no else-branch." diff --git a/csharp/ql/src/Useless code/IntGetHashCode.ql b/csharp/ql/src/Useless code/IntGetHashCode.ql index 57b107a3f8b..c7892fffc65 100644 --- a/csharp/ql/src/Useless code/IntGetHashCode.ql +++ b/csharp/ql/src/Useless code/IntGetHashCode.ql @@ -14,6 +14,7 @@ import csharp import semmle.code.csharp.frameworks.System from MethodCall mc, IntegralType t -where mc.getTarget() instanceof GetHashCodeMethod -and t = mc.getQualifier().getType() +where + mc.getTarget() instanceof GetHashCodeMethod and + t = mc.getQualifier().getType() select mc, "Calling GetHashCode() on type " + t.toStringWithTypes() + " is redundant." diff --git a/csharp/ql/src/Useless code/PointlessForwardingMethod.ql b/csharp/ql/src/Useless code/PointlessForwardingMethod.ql index aff3b9797cf..78513036426 100644 --- a/csharp/ql/src/Useless code/PointlessForwardingMethod.ql +++ b/csharp/ql/src/Useless code/PointlessForwardingMethod.ql @@ -11,45 +11,40 @@ import csharp -predicate methodInClass(ValueOrRefType t, Method m, string name) -{ - m.getDeclaringType() = t - and m.getName() = name +predicate methodInClass(ValueOrRefType t, Method m, string name) { + m.getDeclaringType() = t and + m.getName() = name } -predicate callIn(MethodCall mc, Method fromMethod) -{ - fromMethod = mc.getEnclosingCallable() -} +predicate callIn(MethodCall mc, Method fromMethod) { fromMethod = mc.getEnclosingCallable() } -predicate callTo(MethodCall mc, Method toMethod) -{ +predicate callTo(MethodCall mc, Method toMethod) { toMethod = mc.getTarget().getSourceDeclaration() } -predicate candidates(Method forwarder, Method forwardee) -{ +predicate candidates(Method forwarder, Method forwardee) { exists(ValueOrRefType t, string name | - methodInClass(t, forwarder, name) and methodInClass(t, forwardee, name) | + methodInClass(t, forwarder, name) and methodInClass(t, forwardee, name) + | not ignored(forwarder) and not ignored(forwardee) and forwarder != forwardee ) } -predicate ignored(Method m) -{ - m.isAbstract() - or m.implements() - or m.isOverride() - or m.isVirtual() - or m.getName() = "Dispose" - or not m.fromSource() +predicate ignored(Method m) { + m.isAbstract() or + m.implements() or + m.isOverride() or + m.isVirtual() or + m.getName() = "Dispose" or + not m.fromSource() } from Method forwarder, Method forwardee where - not extractionIsStandalone() - and candidates(forwarder, forwardee) - and forex(MethodCall c | callTo(c, forwardee) | callIn(c, forwarder)) - and forex(MethodCall c | callIn(c, forwarder) | callTo(c, forwardee)) -select forwarder.getSourceDeclaration(), "This method is a forwarder for $@, which is not called independently - the methods can be merged.", + not extractionIsStandalone() and + candidates(forwarder, forwardee) and + forex(MethodCall c | callTo(c, forwardee) | callIn(c, forwarder)) and + forex(MethodCall c | callIn(c, forwarder) | callTo(c, forwardee)) +select forwarder.getSourceDeclaration(), + "This method is a forwarder for $@, which is not called independently - the methods can be merged.", forwardee.getSourceDeclaration(), forwardee.getName() diff --git a/csharp/ql/src/Useless code/RedundantToStringCall.ql b/csharp/ql/src/Useless code/RedundantToStringCall.ql index c257461f80b..f8282dc1a24 100644 --- a/csharp/ql/src/Useless code/RedundantToStringCall.ql +++ b/csharp/ql/src/Useless code/RedundantToStringCall.ql @@ -9,11 +9,13 @@ * @tags maintainability * useless-code */ + import csharp import semmle.code.csharp.commons.Strings import semmle.code.csharp.frameworks.System from MethodCall mc -where mc instanceof ImplicitToStringExpr - and mc.getTarget() instanceof ToStringMethod +where + mc instanceof ImplicitToStringExpr and + mc.getTarget() instanceof ToStringMethod select mc, "Redundant call to 'ToString'." diff --git a/csharp/ql/src/Useless code/UnusedLabel.ql b/csharp/ql/src/Useless code/UnusedLabel.ql index 60a593b4b9d..53ba4180f14 100644 --- a/csharp/ql/src/Useless code/UnusedLabel.ql +++ b/csharp/ql/src/Useless code/UnusedLabel.ql @@ -12,5 +12,5 @@ import csharp from LabelStmt label -where not exists(GotoLabelStmt goto | label=goto.getTarget()) +where not exists(GotoLabelStmt goto | label = goto.getTarget()) select label, "This label is not used." diff --git a/csharp/ql/src/definitions.ql b/csharp/ql/src/definitions.ql index eb1dc8d9eb2..76808724d19 100644 --- a/csharp/ql/src/definitions.ql +++ b/csharp/ql/src/definitions.ql @@ -17,10 +17,13 @@ abstract class Use extends @type_mention_parent { * For more information, see * [LGTM locations](https://lgtm.com/help/ql/locations). */ - 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(Location l | l = this.(Element).getLocation() or - l = this.(TypeMention).getLocation() | + l = this.(TypeMention).getLocation() + | filepath = l.getFile().getAbsolutePath() and startline = l.getStartLine() and startcolumn = l.getStartColumn() and @@ -54,46 +57,37 @@ class MethodUse extends Use, QualifiableExpr { /** Gets the qualifier of this method use, if any. */ private Expr getFormatQualifier() { - if this.getQualifiedDeclaration().(Method).isExtensionMethod() then - result = this.(MethodCall).getArgument(0) - else - result = this.getQualifier() and not result.isImplicit() + if this.getQualifiedDeclaration().(Method).isExtensionMethod() + then result = this.(MethodCall).getArgument(0) + else result = this.getQualifier() and + not result.isImplicit() } - override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { - Use.super.hasLocationInfo(filepath, _, _, _, _) - and - endline = startline - and - endcolumn = startcolumn + this.getQualifiedDeclaration().getName().length() - 1 - and + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + Use.super.hasLocationInfo(filepath, _, _, _, _) and + endline = startline and + endcolumn = startcolumn + this.getQualifiedDeclaration().getName().length() - 1 and ( - exists(Location ql | - ql = this.getFormatQualifier().getLocation() | + exists(Location ql | ql = this.getFormatQualifier().getLocation() | startline = ql.getEndLine() and startcolumn = ql.getEndColumn() + 2 ) or not exists(this.getFormatQualifier()) and - exists(Location l | - l = this.getLocation() | + exists(Location l | l = this.getLocation() | startline = l.getStartLine() and startcolumn = l.getStartColumn() ) ) } - override Method getDefinition() { - result = getQualifiedDeclaration().getSourceDeclaration() - } + override Method getDefinition() { result = getQualifiedDeclaration().getSourceDeclaration() } - override string getUseType() { - result = "M" - } + override string getUseType() { result = "M" } - override string toString() { - result = this.(Expr).toString() - } + override string toString() { result = this.(Expr).toString() } } /** An access. */ @@ -113,9 +107,10 @@ class AccessUse extends Access, Use { not result.isImplicit() } - override predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { - exists(Location ql | - ql = this.getFormatQualifier().getLocation() | + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + exists(Location ql | ql = this.getFormatQualifier().getLocation() | startline = ql.getEndLine() and startcolumn = ql.getEndColumn() + 2 and Use.super.hasLocationInfo(filepath, _, _, endline, endcolumn) @@ -125,22 +120,18 @@ class AccessUse extends Access, Use { Use.super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } - override Declaration getDefinition() { - result = this.getTarget().getSourceDeclaration() - } + override Declaration getDefinition() { result = this.getTarget().getSourceDeclaration() } override string getUseType() { - if this instanceof Call or this instanceof LocalFunctionAccess then - result = "M" - else if this instanceof BaseAccess or this instanceof ThisAccess then - result = "T" + if this instanceof Call or this instanceof LocalFunctionAccess + then result = "M" else - result = "V" + if this instanceof BaseAccess or this instanceof ThisAccess + then result = "T" + else result = "V" } - override string toString() { - result = this.(Access).toString() - } + override string toString() { result = this.(Access).toString() } } /** A type mention. */ @@ -150,7 +141,8 @@ class TypeMentionUse extends Use, TypeMention { // uses for the nested type mentions forall(TypeMention child, Type t | child.getParent() = this and - t = this.getType() | + t = this.getType() + | not t instanceof ArrayType and not t instanceof NullableType and not t instanceof PointerType and @@ -158,23 +150,19 @@ class TypeMentionUse extends Use, TypeMention { ) } - override Type getDefinition() { - result = this.getType().getSourceDeclaration() - } + override Type getDefinition() { result = this.getType().getSourceDeclaration() } override string getUseType() { - if this.getTarget() instanceof ObjectCreation then - result = "M" // constructor call - else - result = "T" + if this.getTarget() instanceof ObjectCreation + then result = "M" // constructor call + else result = "T" } - override string toString() { - result = TypeMention.super.toString() - } + override string toString() { result = TypeMention.super.toString() } } from Use use, Declaration definition -where definition = use.getDefinition() - and definition.fromSource() +where + definition = use.getDefinition() and + definition.fromSource() select use, definition, use.getUseType() diff --git a/csharp/ql/src/external/DuplicateMethod.ql b/csharp/ql/src/external/DuplicateMethod.ql index dc6b245ca0c..57255ce51d0 100644 --- a/csharp/ql/src/external/DuplicateMethod.ql +++ b/csharp/ql/src/external/DuplicateMethod.ql @@ -12,22 +12,29 @@ * statistical * non-attributable */ + import csharp import CodeDuplication predicate relevant(Method m) { m.getNumberOfLinesOfCode() > 5 and not m.getName().matches("get%") - or m.getNumberOfLinesOfCode() > 10 + or + m.getNumberOfLinesOfCode() > 10 } pragma[noopt] predicate query(Method m, Method other) { - duplicateMethod(m, other) - and relevant(m) - and not exists(File f1, File f2 | m.getFile() = f1 and fileLevelDuplication(f1, f2) and other.getFile() = f2) - and not exists(Type t1, Type t2 | m.getDeclaringType() = t1 and classLevelDuplication(t1, t2) and other.getDeclaringType() = t2) + duplicateMethod(m, other) and + relevant(m) and + not exists(File f1, File f2 | + m.getFile() = f1 and fileLevelDuplication(f1, f2) and other.getFile() = f2 + ) and + not exists(Type t1, Type t2 | + m.getDeclaringType() = t1 and classLevelDuplication(t1, t2) and other.getDeclaringType() = t2 + ) } from Method m, Method other where query(m, other) -select m, "Method " + m.getName() + " is duplicated in $@.", other, other.getDeclaringType().getName() + "." + other.getName() +select m, "Method " + m.getName() + " is duplicated in $@.", other, + other.getDeclaringType().getName() + "." + other.getName() diff --git a/csharp/ql/src/external/MostlyDuplicateClass.ql b/csharp/ql/src/external/MostlyDuplicateClass.ql index b5ba22b5b2c..fd4fc87c176 100644 --- a/csharp/ql/src/external/MostlyDuplicateClass.ql +++ b/csharp/ql/src/external/MostlyDuplicateClass.ql @@ -12,10 +12,12 @@ * statistical * non-attributable */ + import csharp import CodeDuplication from Class c, string message, Class link -where mostlyDuplicateClass(c, link, message) - and not fileLevelDuplication(c.getFile(), _) +where + mostlyDuplicateClass(c, link, message) and + not fileLevelDuplication(c.getFile(), _) select c, message, link, link.getName() diff --git a/csharp/ql/src/external/MostlyDuplicateFile.ql b/csharp/ql/src/external/MostlyDuplicateFile.ql index a24a10e5c5d..0100e94bc7c 100644 --- a/csharp/ql/src/external/MostlyDuplicateFile.ql +++ b/csharp/ql/src/external/MostlyDuplicateFile.ql @@ -12,9 +12,11 @@ * statistical * non-attributable */ + import csharp import CodeDuplication from File f, File other, int percent where duplicateFiles(f, other, percent) -select f, percent + "% of the lines in " + f.getBaseName() + " are copies of lines in $@.", other, other.getBaseName() +select f, percent + "% of the lines in " + f.getBaseName() + " are copies of lines in $@.", other, + other.getBaseName() diff --git a/csharp/ql/src/external/MostlyDuplicateMethod.ql b/csharp/ql/src/external/MostlyDuplicateMethod.ql index 75f8041a98c..a7d01ed0ed9 100644 --- a/csharp/ql/src/external/MostlyDuplicateMethod.ql +++ b/csharp/ql/src/external/MostlyDuplicateMethod.ql @@ -11,10 +11,10 @@ * statistical * non-attributable */ + import csharp import CodeDuplication - from Method m, int covered, int total, Method other, int percent where duplicateStatements(m, other, covered, total) and @@ -25,5 +25,5 @@ where not duplicateMethod(m, other) and not classLevelDuplication(m.getDeclaringType(), other.getDeclaringType()) and not fileLevelDuplication(m.getFile(), other.getFile()) -select m, percent + "% of the statements in " + m.getName() + " are duplicated in $@.", - other, other.getDeclaringType().getName() + "." + other.getName() +select m, percent + "% of the statements in " + m.getName() + " are duplicated in $@.", other, + other.getDeclaringType().getName() + "." + other.getName() diff --git a/csharp/ql/src/external/MostlySimilarFile.ql b/csharp/ql/src/external/MostlySimilarFile.ql index 4e0ae9bb3c3..1c175a72bbd 100644 --- a/csharp/ql/src/external/MostlySimilarFile.ql +++ b/csharp/ql/src/external/MostlySimilarFile.ql @@ -12,17 +12,19 @@ * statistical * non-attributable */ + import csharp import CodeDuplication predicate irrelevant(File f) { - f.getStem() = "AssemblyInfo" - or f.getStem().matches("%.Designer") + f.getStem() = "AssemblyInfo" or + f.getStem().matches("%.Designer") } from File f, File other, int percent where - similarFiles(f, other, percent) - and not irrelevant(f) - and not irrelevant(other) -select f, percent + "% of the lines in " + f.getBaseName() + " are similar to lines in $@.", other, other.getBaseName() + similarFiles(f, other, percent) and + not irrelevant(f) and + not irrelevant(other) +select f, percent + "% of the lines in " + f.getBaseName() + " are similar to lines in $@.", other, + other.getBaseName() diff --git a/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql b/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql index 96e2e7764e7..209d580bc19 100644 --- a/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql +++ b/csharp/ql/src/external/examples/filters/BumpMetricBy10.ql @@ -3,9 +3,9 @@ * @description Add 10 to a metric's value * @deprecated */ + import csharp import external.MetricFilter from MetricResult res -select res, - res.getValue() + 10 +select res, res.getValue() + 10 diff --git a/csharp/ql/src/external/examples/filters/EditDefectMessage.ql b/csharp/ql/src/external/examples/filters/EditDefectMessage.ql index d42fe41f556..4fbf4146550 100644 --- a/csharp/ql/src/external/examples/filters/EditDefectMessage.ql +++ b/csharp/ql/src/external/examples/filters/EditDefectMessage.ql @@ -3,9 +3,9 @@ * @description Change the string in the select to edit the message * @deprecated */ + import csharp import external.DefectFilter from DefectResult res -select res, - "Filtered query result: " + res.getMessage() +select res, "Filtered query result: " + res.getMessage() diff --git a/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql b/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql index c52c5ee2da4..2a1257427b2 100644 --- a/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql +++ b/csharp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql @@ -3,14 +3,12 @@ * @description Shows how to exclude certain files or folders from results. * @deprecated */ + import csharp import external.DefectFilter -predicate generatedFile(File f) { - f.getAbsolutePath().matches("%generated%") -} +predicate generatedFile(File f) { f.getAbsolutePath().matches("%generated%") } from DefectResult res where not generatedFile(res.getFile()) -select res, - res.getMessage() +select res, res.getMessage() diff --git a/csharp/ql/src/external/examples/filters/FromSource.ql b/csharp/ql/src/external/examples/filters/FromSource.ql index 6577ce77800..2f714ec2225 100644 --- a/csharp/ql/src/external/examples/filters/FromSource.ql +++ b/csharp/ql/src/external/examples/filters/FromSource.ql @@ -3,10 +3,10 @@ * @description Shows how to filter for only certain files * @deprecated */ + import csharp import external.DefectFilter from DefectResult res where res.getFile().fromSource() -select res, - res.getMessage() +select res, res.getMessage() diff --git a/csharp/ql/src/external/examples/filters/RecentDefects.ql b/csharp/ql/src/external/examples/filters/RecentDefects.ql index 430cafca7a9..687baf6d914 100644 --- a/csharp/ql/src/external/examples/filters/RecentDefects.ql +++ b/csharp/ql/src/external/examples/filters/RecentDefects.ql @@ -3,17 +3,15 @@ * @description Filter a defect query to only include results in files that have been changed recently, and modify the message. * @deprecated */ + import csharp import external.DefectFilter import external.VCS private predicate recent(File file) { - exists(Commit e | file = e.getAnAffectedFile() | - e.isRecent() - ) + exists(Commit e | file = e.getAnAffectedFile() | e.isRecent()) } from DefectResult res where recent(res.getFile()) -select res, - "Recent: " + res.getMessage() +select res, "Recent: " + res.getMessage() diff --git a/csharp/ql/src/external/examples/multipleArtifacts/CodeFilesUsuallyEditedTogether.ql b/csharp/ql/src/external/examples/multipleArtifacts/CodeFilesUsuallyEditedTogether.ql index bdbd1ced08c..544b49f9838 100644 --- a/csharp/ql/src/external/examples/multipleArtifacts/CodeFilesUsuallyEditedTogether.ql +++ b/csharp/ql/src/external/examples/multipleArtifacts/CodeFilesUsuallyEditedTogether.ql @@ -5,17 +5,16 @@ * @problem.severity recommendation * @deprecated */ + import csharp import external.VCS int numberOfCommitsWith(File a, File b) { - result = count(Commit e | a = e.getAnAffectedFile() and b = e.getAnAffectedFile()) - and a != b + result = count(Commit e | a = e.getAnAffectedFile() and b = e.getAnAffectedFile()) and + a != b } -int totalCommits(File a) { - result = count(Commit e | a = e.getAnAffectedFile()) -} +int totalCommits(File a) { result = count(Commit e | a = e.getAnAffectedFile()) } int percentagePairedCommits(File f, File with) { exists(int paired, int total | @@ -27,8 +26,9 @@ int percentagePairedCommits(File f, File with) { } from File f, File other, int percent, int total -where percent = percentagePairedCommits(f, other) and - total = totalCommits(f) and - percent >= 70 and - total >= 4 +where + percent = percentagePairedCommits(f, other) and + total = totalCommits(f) and + percent >= 70 and + total >= 4 select f, "This file is usually edited together with " + other + " (" + percent + "% of commits)." diff --git a/csharp/ql/src/external/examples/multipleArtifacts/LargeFilesCurrentlyEdited.ql b/csharp/ql/src/external/examples/multipleArtifacts/LargeFilesCurrentlyEdited.ql index ec516bd60d0..aaa7e9768ca 100644 --- a/csharp/ql/src/external/examples/multipleArtifacts/LargeFilesCurrentlyEdited.ql +++ b/csharp/ql/src/external/examples/multipleArtifacts/LargeFilesCurrentlyEdited.ql @@ -5,13 +5,16 @@ * @problem.severity warning * @deprecated */ + import csharp import external.VCS from File f, int numRecent, int loc -where numRecent = strictcount(Commit e | f = e.getAnAffectedFile() and e.isRecent()) - and loc = f.getNumberOfLinesOfCode() - and loc > 500 - and numRecent > 0 -select f, "Large file (" + loc.toString() + " lines of code) actively being edited (" + - numRecent.toString() + " recent commits)." +where + numRecent = strictcount(Commit e | f = e.getAnAffectedFile() and e.isRecent()) and + loc = f.getNumberOfLinesOfCode() and + loc > 500 and + numRecent > 0 +select f, + "Large file (" + loc.toString() + " lines of code) actively being edited (" + numRecent.toString() + + " recent commits)." diff --git a/csharp/ql/src/external/examples/multipleArtifacts/PoorlyDocumentedFilesWithManyAuthors.ql b/csharp/ql/src/external/examples/multipleArtifacts/PoorlyDocumentedFilesWithManyAuthors.ql index 26fa26c1f75..6f87aa3f7b1 100644 --- a/csharp/ql/src/external/examples/multipleArtifacts/PoorlyDocumentedFilesWithManyAuthors.ql +++ b/csharp/ql/src/external/examples/multipleArtifacts/PoorlyDocumentedFilesWithManyAuthors.ql @@ -5,18 +5,21 @@ * @problem.severity warning * @deprecated */ + import csharp import external.VCS predicate fileCommentRatio(File f, float ratio) { - ratio = 100.0 * ((float)f.getNumberOfLinesOfComments() / (float)f.getNumberOfLinesOfCode()) + ratio = 100.0 * (f.getNumberOfLinesOfComments().(float) / f.getNumberOfLinesOfCode().(float)) } from File f, int numAuthors, float docPercent -where numAuthors = strictcount(Author a | f = a.getAnEditedFile()) - and fileCommentRatio(f, docPercent) - and docPercent < 20.0 - and numAuthors >= 3 - and f.getNumberOfLinesOfCode() > 150 -select f, "Poorly documented file (" + docPercent.floor().toString() + "% comments) with " + - numAuthors.toString() + " authors." +where + numAuthors = strictcount(Author a | f = a.getAnEditedFile()) and + fileCommentRatio(f, docPercent) and + docPercent < 20.0 and + numAuthors >= 3 and + f.getNumberOfLinesOfCode() > 150 +select f, + "Poorly documented file (" + docPercent.floor().toString() + "% comments) with " + + numAuthors.toString() + " authors." diff --git a/csharp/ql/src/external/examples/svn/NumberOfAuthorsPerFile.ql b/csharp/ql/src/external/examples/svn/NumberOfAuthorsPerFile.ql index 500ca578561..e040e22e958 100644 --- a/csharp/ql/src/external/examples/svn/NumberOfAuthorsPerFile.ql +++ b/csharp/ql/src/external/examples/svn/NumberOfAuthorsPerFile.ql @@ -6,11 +6,12 @@ * @metricAggregate avg * @deprecated */ + import csharp import external.VCS from File f, int n -where n = count(Author author | author.getAnEditedFile() = f) - and f.fromSource() -select f, n -order by n desc +where + n = count(Author author | author.getAnEditedFile() = f) and + f.fromSource() +select f, n order by n desc diff --git a/csharp/ql/src/external/examples/svn/NumberOfChangesPerFile.ql b/csharp/ql/src/external/examples/svn/NumberOfChangesPerFile.ql index 0383cc4c278..3021f6f6c14 100644 --- a/csharp/ql/src/external/examples/svn/NumberOfChangesPerFile.ql +++ b/csharp/ql/src/external/examples/svn/NumberOfChangesPerFile.ql @@ -6,11 +6,12 @@ * @metricType file * @deprecated */ + import csharp import external.VCS from File f, int n -where n = count(Commit svn | f = svn.getAnAffectedFile()) - and n > 1 -select f, n -order by n desc +where + n = count(Commit svn | f = svn.getAnAffectedFile()) and + n > 1 +select f, n order by n desc diff --git a/csharp/ql/src/external/examples/svn/NumberOfRecentCommits.ql b/csharp/ql/src/external/examples/svn/NumberOfRecentCommits.ql index 45263d3305a..6ad790eb56d 100644 --- a/csharp/ql/src/external/examples/svn/NumberOfRecentCommits.ql +++ b/csharp/ql/src/external/examples/svn/NumberOfRecentCommits.ql @@ -6,12 +6,12 @@ * @metricType file * @deprecated */ + import csharp import external.VCS from File f, int n -where n = count(Commit e | e.getAnAffectedFile() = f and e.isRecent()) - and n > 0 -select f, n -order by n desc - +where + n = count(Commit e | e.getAnAffectedFile() = f and e.isRecent()) and + n > 0 +select f, n order by n desc diff --git a/csharp/ql/src/external/tests/DefectFilter.ql b/csharp/ql/src/external/tests/DefectFilter.ql index 537143927aa..c0637beb2db 100644 --- a/csharp/ql/src/external/tests/DefectFilter.ql +++ b/csharp/ql/src/external/tests/DefectFilter.ql @@ -3,6 +3,7 @@ * @description Only include results in large files (200) lines of code, and change the message. * @deprecated */ + import csharp import external.DefectFilter import external.VCS diff --git a/csharp/ql/src/external/tests/DefectFromExternalData.ql b/csharp/ql/src/external/tests/DefectFromExternalData.ql index a93965f69e2..70557f357a3 100644 --- a/csharp/ql/src/external/tests/DefectFromExternalData.ql +++ b/csharp/ql/src/external/tests/DefectFromExternalData.ql @@ -7,11 +7,13 @@ */ import csharp - import external.ExternalArtifact // custom://[FileUtil][2011-01-02][false][1.1][6][Message 2] from ExternalData d, File u -where d.getQueryPath() = "external-data.ql" - and u.getStem() = d.getField(0) -select u, d.getField(5) + ", " + d.getFieldAsDate(1) + ", " +d.getField(2) + ", " + d.getFieldAsFloat(3) + ", " + d.getFieldAsInt(4) + ": " + d.getNumFields() +where + d.getQueryPath() = "external-data.ql" and + u.getStem() = d.getField(0) +select u, + d.getField(5) + ", " + d.getFieldAsDate(1) + ", " + d.getField(2) + ", " + d.getFieldAsFloat(3) + + ", " + d.getFieldAsInt(4) + ": " + d.getNumFields() diff --git a/csharp/ql/src/external/tests/DefectFromExternalDefect.ql b/csharp/ql/src/external/tests/DefectFromExternalDefect.ql index 74b4982a4fe..57138a6879f 100644 --- a/csharp/ql/src/external/tests/DefectFromExternalDefect.ql +++ b/csharp/ql/src/external/tests/DefectFromExternalDefect.ql @@ -5,8 +5,8 @@ * @problem.severity warning * @deprecated */ -import csharp +import csharp import external.ExternalArtifact class DuplicateCode extends ExternalDefect { diff --git a/csharp/ql/src/external/tests/DefectFromExternalMetric.ql b/csharp/ql/src/external/tests/DefectFromExternalMetric.ql index 97aedc668a1..88d38d5f00b 100644 --- a/csharp/ql/src/external/tests/DefectFromExternalMetric.ql +++ b/csharp/ql/src/external/tests/DefectFromExternalMetric.ql @@ -5,12 +5,13 @@ * @problem.severity warning * @deprecated */ -import csharp +import csharp import external.ExternalArtifact from ExternalMetric m, File f -where m.getQueryPath() = "filesBuilt.ql" - and m.getValue() = 1.0 - and m.getFile() = f +where + m.getQueryPath() = "filesBuilt.ql" and + m.getValue() = 1.0 and + m.getFile() = f select f, "File is built" diff --git a/csharp/ql/src/external/tests/DefectFromSVN.ql b/csharp/ql/src/external/tests/DefectFromSVN.ql index ccdca3e8851..e7b02afd373 100644 --- a/csharp/ql/src/external/tests/DefectFromSVN.ql +++ b/csharp/ql/src/external/tests/DefectFromSVN.ql @@ -7,21 +7,13 @@ */ import csharp - import external.ExternalArtifact import external.VCS -predicate numCommits(File f, int i) { - i = count(Commit e | e.getAnAffectedFile() = f) -} +predicate numCommits(File f, int i) { i = count(Commit e | e.getAnAffectedFile() = f) } -predicate maxCommits(int i) { - i = max(File f, int j | numCommits(f, j) | j) -} +predicate maxCommits(int i) { i = max(File f, int j | numCommits(f, j) | j) } from File f, int i -where numCommits(f,i) and maxCommits(i) +where numCommits(f, i) and maxCommits(i) select f, "This file has " + i + " commits." - - - diff --git a/csharp/ql/src/external/tests/MetricFilter.ql b/csharp/ql/src/external/tests/MetricFilter.ql index 4b7c879ffad..9f79465be75 100644 --- a/csharp/ql/src/external/tests/MetricFilter.ql +++ b/csharp/ql/src/external/tests/MetricFilter.ql @@ -4,6 +4,7 @@ * @kind treemap * @deprecated */ + import csharp import external.MetricFilter diff --git a/csharp/ql/src/external/tests/MetricFromExternalDefect.ql b/csharp/ql/src/external/tests/MetricFromExternalDefect.ql index 65483a4bd49..4894de28761 100644 --- a/csharp/ql/src/external/tests/MetricFromExternalDefect.ql +++ b/csharp/ql/src/external/tests/MetricFromExternalDefect.ql @@ -8,18 +8,14 @@ */ import csharp - import external.ExternalArtifact class DuplicateCode extends ExternalDefect { DuplicateCode() { getQueryPath() = "duplicate-code/duplicateCode.ql" } } -predicate numDuplicateEntries(File f, int i) { - i = count(DuplicateCode d | d.getFile() = f) -} +predicate numDuplicateEntries(File f, int i) { i = count(DuplicateCode d | d.getFile() = f) } from File f, int i where numDuplicateEntries(f, i) select f, i - diff --git a/csharp/ql/src/external/tests/MetricFromExternalMetric.ql b/csharp/ql/src/external/tests/MetricFromExternalMetric.ql index 6eb475ac09f..11a63134b8c 100644 --- a/csharp/ql/src/external/tests/MetricFromExternalMetric.ql +++ b/csharp/ql/src/external/tests/MetricFromExternalMetric.ql @@ -8,16 +8,17 @@ */ import csharp - import external.ExternalArtifact predicate numBuiltFiles(Folder fold, int i) { i = count(File f | - exists(ExternalMetric m | m.getQueryPath() = "filesBuilt.ql" and - m.getValue() = 1.0 and - m.getFile() = f) and - f.getParentContainer() = fold - ) + exists(ExternalMetric m | + m.getQueryPath() = "filesBuilt.ql" and + m.getValue() = 1.0 and + m.getFile() = f + ) and + f.getParentContainer() = fold + ) } from File f, int i diff --git a/csharp/ql/src/external/tests/MetricFromSVN.ql b/csharp/ql/src/external/tests/MetricFromSVN.ql index 76effd991b0..9836229766e 100644 --- a/csharp/ql/src/external/tests/MetricFromSVN.ql +++ b/csharp/ql/src/external/tests/MetricFromSVN.ql @@ -8,12 +8,9 @@ */ import csharp - import external.VCS -predicate numCommits(File f, int i) { - i = count(Commit e | e.getAnAffectedFile() = f) -} +predicate numCommits(File f, int i) { i = count(Commit e | e.getAnAffectedFile() = f) } from File f, int i where numCommits(f, i) diff --git a/csharp/ql/src/filters/ChangedLines.ql b/csharp/ql/src/filters/ChangedLines.ql index dcc3c0b7467..2bc3c1c4fe4 100644 --- a/csharp/ql/src/filters/ChangedLines.ql +++ b/csharp/ql/src/filters/ChangedLines.ql @@ -4,6 +4,7 @@ * @id cs/changed-lines-filter * @kind problem */ + import csharp import external.ExternalArtifact import external.DefectFilter @@ -11,7 +12,9 @@ import ChangedLines from DefectResult res where - changedLine(res.getFile(), res.getStartLine()) or - changedLine(res.getFile(), res.getEndLine()) or - (res.getStartLine() = 0 and changedLine(res.getFile(),_)) + changedLine(res.getFile(), res.getStartLine()) + or + changedLine(res.getFile(), res.getEndLine()) + or + (res.getStartLine() = 0 and changedLine(res.getFile(), _)) select res, res.getMessage() diff --git a/csharp/ql/src/filters/ChangedLinesForMetric.ql b/csharp/ql/src/filters/ChangedLinesForMetric.ql index acbe17ac10b..d04cc681a37 100644 --- a/csharp/ql/src/filters/ChangedLinesForMetric.ql +++ b/csharp/ql/src/filters/ChangedLinesForMetric.ql @@ -4,12 +4,12 @@ * @id cs/changed-lines-metric-filter * @kind treemap */ + import csharp import external.ExternalArtifact import external.MetricFilter import ChangedLines from MetricResult res -where - changedLine(res.getFile(),_) +where changedLine(res.getFile(), _) select res, res.getValue() diff --git a/csharp/ql/src/filters/FromSource.ql b/csharp/ql/src/filters/FromSource.ql index bfb6be8f11e..e19785afad9 100644 --- a/csharp/ql/src/filters/FromSource.ql +++ b/csharp/ql/src/filters/FromSource.ql @@ -4,10 +4,10 @@ * @kind problem * @id cs/source-filter */ + import csharp import external.DefectFilter from DefectResult res where res.getFile().fromSource() -select res, - res.getMessage() +select res, res.getMessage() diff --git a/csharp/ql/src/filters/FromSourceForMetric.ql b/csharp/ql/src/filters/FromSourceForMetric.ql index e275d904df3..49e1d4a2f3c 100644 --- a/csharp/ql/src/filters/FromSourceForMetric.ql +++ b/csharp/ql/src/filters/FromSourceForMetric.ql @@ -4,10 +4,10 @@ * @kind treemap * @id cs/source-metric-filter */ + import csharp import external.MetricFilter from MetricResult res where res.getFile().fromSource() -select res, - res.getValue() +select res, res.getValue() diff --git a/csharp/ql/src/filters/NotGenerated.ql b/csharp/ql/src/filters/NotGenerated.ql index a55332b509e..5e80ffe8e2e 100644 --- a/csharp/ql/src/filters/NotGenerated.ql +++ b/csharp/ql/src/filters/NotGenerated.ql @@ -4,10 +4,10 @@ * @kind problem * @id cs/not-generated-file-filter */ + import semmle.code.csharp.commons.GeneratedCode import external.DefectFilter from DefectResult res where not isGeneratedCode(res.getFile()) -select res, - res.getMessage() +select res, res.getMessage() diff --git a/csharp/ql/src/filters/NotGeneratedForMetric.ql b/csharp/ql/src/filters/NotGeneratedForMetric.ql index 5d2ce663de8..ca6e7f8080f 100644 --- a/csharp/ql/src/filters/NotGeneratedForMetric.ql +++ b/csharp/ql/src/filters/NotGeneratedForMetric.ql @@ -4,10 +4,10 @@ * @kind treemap * @id cs/not-generated-file-metric-filter */ + import semmle.code.csharp.commons.GeneratedCode import external.MetricFilter from MetricResult res where not isGeneratedCode(res.getFile()) -select res, - res.getValue() +select res, res.getValue() diff --git a/csharp/ql/src/filters/NotInTestFile.ql b/csharp/ql/src/filters/NotInTestFile.ql index db1da42d8ee..c685a5cab2b 100644 --- a/csharp/ql/src/filters/NotInTestFile.ql +++ b/csharp/ql/src/filters/NotInTestFile.ql @@ -4,11 +4,11 @@ * @kind problem * @id cs/test-file-filter */ + import csharp import semmle.code.csharp.frameworks.Test import external.DefectFilter from DefectResult res -where not(res.getFile() instanceof TestFile) -select res, - res.getMessage() +where not (res.getFile() instanceof TestFile) +select res, res.getMessage() diff --git a/csharp/ql/src/filters/NotInTestFileForMetric.ql b/csharp/ql/src/filters/NotInTestFileForMetric.ql index 03529f6067c..da68c57d415 100644 --- a/csharp/ql/src/filters/NotInTestFileForMetric.ql +++ b/csharp/ql/src/filters/NotInTestFileForMetric.ql @@ -4,11 +4,11 @@ * @kind treemap * @id cs/test-file-metric-filter */ + import csharp import semmle.code.csharp.frameworks.Test import external.MetricFilter from MetricResult res -where not(res.getFile() instanceof TestFile) -select res, - res.getValue() +where not (res.getFile() instanceof TestFile) +select res, res.getValue() diff --git a/csharp/ql/src/filters/NotInTestMethod.ql b/csharp/ql/src/filters/NotInTestMethod.ql index 38ecd572fba..282ef770b7d 100644 --- a/csharp/ql/src/filters/NotInTestMethod.ql +++ b/csharp/ql/src/filters/NotInTestMethod.ql @@ -4,12 +4,14 @@ * @kind problem * @id cs/test-method-filter */ + import csharp import semmle.code.csharp.frameworks.Test import external.DefectFilter from DefectResult res -where not(res.getFile() instanceof TestFile) or - not(res.getStartLine() = res.getFile().(TestFile).lineInTestMethod()) -select res, - res.getMessage() +where + not (res.getFile() instanceof TestFile) + or + not (res.getStartLine() = res.getFile().(TestFile).lineInTestMethod()) +select res, res.getMessage() diff --git a/csharp/ql/src/filters/NotInTestMethodExpectingException.ql b/csharp/ql/src/filters/NotInTestMethodExpectingException.ql index 175579bfbec..ec1ec780c6c 100644 --- a/csharp/ql/src/filters/NotInTestMethodExpectingException.ql +++ b/csharp/ql/src/filters/NotInTestMethodExpectingException.ql @@ -4,6 +4,7 @@ * @kind problem * @id cs/test-method-exception-filter */ + import csharp import semmle.code.csharp.frameworks.Test import external.DefectFilter @@ -16,7 +17,8 @@ predicate ignoredLine(File f, int line) { } from DefectResult res -where not(res.getFile() instanceof TestFile) or +where + not (res.getFile() instanceof TestFile) + or not ignoredLine(res.getFile(), res.getStartLine()) -select res, - res.getMessage() +select res, res.getMessage() diff --git a/csharp/ql/src/filters/RecentDefects.ql b/csharp/ql/src/filters/RecentDefects.ql index ff73ead990d..38dea3dce46 100644 --- a/csharp/ql/src/filters/RecentDefects.ql +++ b/csharp/ql/src/filters/RecentDefects.ql @@ -4,14 +4,13 @@ * @kind problem * @id cs/recently-changed-file-filter */ + import csharp import external.DefectFilter import external.VCS private predicate recent(File file) { - exists(Commit e | file = e.getAnAffectedFile() | - e.isRecent() - ) + exists(Commit e | file = e.getAnAffectedFile() | e.isRecent()) } from DefectResult res diff --git a/csharp/ql/src/filters/UnchangedLines.ql b/csharp/ql/src/filters/UnchangedLines.ql index f6ff210c15c..7274cd59506 100644 --- a/csharp/ql/src/filters/UnchangedLines.ql +++ b/csharp/ql/src/filters/UnchangedLines.ql @@ -4,6 +4,7 @@ * @kind problem * @id cs/unchanged-lines-filter */ + import csharp import external.ExternalArtifact import external.DefectFilter @@ -12,8 +13,10 @@ import ChangedLines from DefectResult res where not ( - changedLine(res.getFile(), res.getStartLine()) or - changedLine(res.getFile(), res.getEndLine()) or - (res.getStartLine() = 0 and changedLine(res.getFile(),_)) + changedLine(res.getFile(), res.getStartLine()) + or + changedLine(res.getFile(), res.getEndLine()) + or + (res.getStartLine() = 0 and changedLine(res.getFile(), _)) ) select res, res.getMessage() diff --git a/csharp/ql/src/filters/UnchangedLinesForMetric.ql b/csharp/ql/src/filters/UnchangedLinesForMetric.ql index cbb222a9a23..b31b4cb5d56 100644 --- a/csharp/ql/src/filters/UnchangedLinesForMetric.ql +++ b/csharp/ql/src/filters/UnchangedLinesForMetric.ql @@ -4,12 +4,12 @@ * @kind treemap * @id cs/unchanged-lines-metric-filter */ + import csharp import external.ExternalArtifact import external.MetricFilter import ChangedLines from MetricResult res -where - not changedLine(res.getFile(),_) +where not changedLine(res.getFile(), _) select res, res.getValue()