This commit is contained in:
Tom Hvitved 2019-01-02 12:59:07 +01:00
Родитель 4348de3120
Коммит daa45322b1
277 изменённых файлов: 2462 добавлений и 2301 удалений

Просмотреть файл

@ -8,12 +8,13 @@
* @tags efficiency * @tags efficiency
* maintainability * maintainability
*/ */
import csharp import csharp
from MethodCall c, Method gcCollect from MethodCall c, Method gcCollect
where where
c.getTarget() = gcCollect c.getTarget() = gcCollect and
and gcCollect.hasName("Collect") gcCollect.hasName("Collect") and
and gcCollect.hasNoParameters() gcCollect.hasNoParameters() and
and gcCollect.getDeclaringType().hasQualifiedName("System.GC") gcCollect.getDeclaringType().hasQualifiedName("System.GC")
select c, "Call to 'GC.Collect()'." select c, "Call to 'GC.Collect()'."

Просмотреть файл

@ -14,13 +14,12 @@
import csharp import csharp
class ObsoleteAttribute extends Attribute { class ObsoleteAttribute extends Attribute {
ObsoleteAttribute() { ObsoleteAttribute() { this.getType().hasQualifiedName("System", "ObsoleteAttribute") }
this.getType().hasQualifiedName("System", "ObsoleteAttribute")
}
} }
from MethodCall c, Method m from MethodCall c, Method m
where m = c.getTarget() where
and m.getAnAttribute() instanceof ObsoleteAttribute m = c.getTarget() and
and not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute m.getAnAttribute() instanceof ObsoleteAttribute and
not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute
select c, "Call to obsolete method $@.", m, m.getName() select c, "Call to obsolete method $@.", m, m.getName()

Просмотреть файл

@ -16,28 +16,30 @@ import semmle.code.csharp.frameworks.System
from Class c, Element item, string message, string itemText from Class c, Element item, string message, string itemText
where where
c.isSourceDeclaration() c.isSourceDeclaration() and
and not implementsEquals(c) not implementsEquals(c) and
and not c.isAbstract() not c.isAbstract() and
and
( (
exists(MethodCall callToEquals | exists(MethodCall callToEquals |
callToEquals.getTarget() instanceof EqualsMethod callToEquals.getTarget() instanceof EqualsMethod and
and callToEquals.getQualifier().getType() = c callToEquals.getQualifier().getType() = c and
and message = "but it is called $@" message = "but it is called $@" and
and item = callToEquals item = callToEquals and
and itemText = "here" ) itemText = "here"
)
or or
( item = c.getAnOperator().(EQOperator) (
and message = "but it implements $@" item = c.getAnOperator().(EQOperator) and
and itemText = "operator ==" ) message = "but it implements $@" and
itemText = "operator =="
)
or or
exists(IEquatableEqualsMethod eq | item = eq exists(IEquatableEqualsMethod eq |
and eq = c.getAMethod() item = eq and
and message = "but it implements $@" eq = c.getAMethod() and
and itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals" message = "but it implements $@" and
itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals"
) )
) )
select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".", item,
select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".", itemText
item, itemText

Просмотреть файл

@ -14,8 +14,8 @@ import csharp
from ValueOrRefType c from ValueOrRefType c
where where
c.fromSource() c.fromSource() and
and c.getABaseInterface+().hasQualifiedName("System", "ICloneable") c.getABaseInterface+().hasQualifiedName("System", "ICloneable") and
and not c.isSealed() not c.isSealed() and
and exists(Method m | m.getDeclaringType() = c and m.hasName("Clone")) exists(Method m | m.getDeclaringType() = c and m.hasName("Clone"))
select c, "Class '" + c.getName() + "' implements 'ICloneable'." select c, "Class '" + c.getName() + "' implements 'ICloneable'."

Просмотреть файл

@ -29,7 +29,8 @@ ExceptionClass getAThrownException(Method m) {
or or
exists(ControlFlowElement cfe | exists(ControlFlowElement cfe |
cfe = any(ThrowElement te | result = te.getExpr().getType()) or 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 cfe.getEnclosingCallable() = m and
not isTriedAgainstException(cfe, result) 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 * Holds if control flow element is tried against throwing an exception of type
* `ec`. * `ec`.
*/ */
pragma [noinline] pragma[noinline]
predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) { predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) {
(cfe instanceof ThrowElement or cfe instanceof MethodCall) and (cfe instanceof ThrowElement or cfe instanceof MethodCall) and
exists(TryStmt ts | exists(TryStmt ts |
@ -53,22 +54,27 @@ predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) {
*/ */
predicate disposeReachableFromDisposableCreation(MethodCall disposeCall, Expr disposableCreation) { predicate disposeReachableFromDisposableCreation(MethodCall disposeCall, Expr disposableCreation) {
// The qualifier of the Dispose call flows from something that introduced a disposable into scope // 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())) disposableCreation instanceof LocalScopeDisposableCreation or
and disposeCall.getTarget() instanceof DisposeMethod 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 from MethodCall disposeCall, Expr disposableCreation, MethodCall callThatThrows
where where
disposeReachableFromDisposableCreation(disposeCall, disposableCreation) disposeReachableFromDisposableCreation(disposeCall, disposableCreation) and
// The dispose call is not, itself, within a dispose method. // 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 // Dispose call not within a finally or catch block
and not exists(TryStmt ts | not exists(TryStmt ts |
ts.getACatchClause().getAChild*() = disposeCall or ts.getFinally().getAChild*() = disposeCall) ts.getACatchClause().getAChild*() = disposeCall or ts.getFinally().getAChild*() = disposeCall
) and
// At least one method call exists between the allocation and disposal that could throw // At least one method call exists between the allocation and disposal that could throw
and disposableCreation.getAReachableElement() = callThatThrows disposableCreation.getAReachableElement() = callThatThrows and
and callThatThrows.getAReachableElement() = disposeCall callThatThrows.getAReachableElement() = disposeCall and
and exists(getAThrownException(callThatThrows.getARuntimeTarget())) exists(getAThrownException(callThatThrows.getARuntimeTarget()))
select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows, callThatThrows.toString() select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows,
callThatThrows.toString()

Просмотреть файл

@ -13,8 +13,9 @@ import csharp
import semmle.code.csharp.frameworks.Format import semmle.code.csharp.frameworks.Format
from FormatCall format, ValidFormatString src, int used, int supplied from FormatCall format, ValidFormatString src, int used, int supplied
where src = format.getAFormatSource() where
and used = src.getAnInsert() src = format.getAFormatSource() and
and supplied = format.getSuppliedArguments() used = src.getAnInsert() and
and used >= supplied supplied = format.getSuppliedArguments() and
used >= supplied
select format, "Argument '{" + used + "}' has not been supplied to $@ format string.", src, "this" select format, "Argument '{" + used + "}' has not been supplied to $@ format string.", src, "this"

Просмотреть файл

@ -13,6 +13,8 @@ import csharp
import semmle.code.csharp.frameworks.Format import semmle.code.csharp.frameworks.Format
from FormatCall format, int unused, ValidFormatString src from FormatCall format, int unused, ValidFormatString src
where src = format.getAFormatSource() where
and unused = format.getAnUnusedArgument(src) src = format.getAFormatSource() and
select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused), "this supplied value" unused = format.getAnUnusedArgument(src)
select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused),
"this supplied value"

Просмотреть файл

@ -10,22 +10,25 @@
* maintainability * maintainability
* external/cwe/cwe-581 * external/cwe/cwe-581
*/ */
import csharp import csharp
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
from Class c, Method present, string missing 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 not c.getAMethod() instanceof GetHashCodeMethod and
missing = "GetHashCode()" missing = "GetHashCode()"
) or )
or
( (
present = (GetHashCodeMethod)c.getAMethod() and present = c.getAMethod().(GetHashCodeMethod) and
not implementsEquals(c) and not implementsEquals(c) and
missing = "Equals(object)" missing = "Equals(object)"
) )
) )
select c, "Class '" + c.getName() + "' overrides $@, but not " + missing + ".", select c, "Class '" + c.getName() + "' overrides $@, but not " + missing + ".", present,
present, present.getName() present.getName()

Просмотреть файл

@ -13,8 +13,7 @@ import csharp
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
predicate implementsIComparable(ValueOrRefType t, Type paramType) { predicate implementsIComparable(ValueOrRefType t, Type paramType) {
exists(ConstructedType ct | exists(ConstructedType ct | t.getABaseType+() = ct |
t.getABaseType+() = ct |
ct = any(SystemIComparableTInterface i).getAConstructedGeneric() and ct = any(SystemIComparableTInterface i).getAConstructedGeneric() and
paramType = ct.getATypeArgument() paramType = ct.getATypeArgument()
) )
@ -28,20 +27,21 @@ predicate implementsIComparable(ValueOrRefType t, Type paramType) {
} }
predicate compareToMethod(Method m, Type paramType) { predicate compareToMethod(Method m, Type paramType) {
m.hasName("CompareTo") m.hasName("CompareTo") and
and m.fromSource() m.fromSource() and
and m.isPublic() m.isPublic() and
and m.getReturnType() instanceof IntType m.getReturnType() instanceof IntType and
and m.getNumberOfParameters() = 1 m.getNumberOfParameters() = 1 and
and paramType = m.getAParameter().getType() paramType = m.getAParameter().getType()
} }
from Method m, RefType declaringType, Type actualParamType from Method m, RefType declaringType, Type actualParamType
where m.isSourceDeclaration() where
and declaringType = m.getDeclaringType() m.isSourceDeclaration() and
and compareToMethod(m, actualParamType) declaringType = m.getDeclaringType() and
and not implementsIComparable(declaringType, actualParamType) compareToMethod(m, actualParamType) and
select m, "The parameter of this 'CompareTo' method is of type $@, but $@ does not implement 'IComparable<$@>'.", not implementsIComparable(declaringType, actualParamType)
actualParamType, actualParamType.getName(), select m,
declaringType, declaringType.getName(), "The parameter of this 'CompareTo' method is of type $@, but $@ does not implement 'IComparable<$@>'.",
actualParamType, actualParamType.getName(), declaringType, declaringType.getName(),
actualParamType, actualParamType.getName() actualParamType, actualParamType.getName()

Просмотреть файл

@ -14,21 +14,22 @@ import semmle.code.csharp.frameworks.System
class EqualsOtherMethod extends Method { class EqualsOtherMethod extends Method {
EqualsOtherMethod() { EqualsOtherMethod() {
this.hasName("Equals") this.hasName("Equals") and
and this.getNumberOfParameters() = 1 this.getNumberOfParameters() = 1 and
and this.getReturnType() instanceof BoolType this.getReturnType() instanceof BoolType and
and this.getDeclaringType() instanceof Class this.getDeclaringType() instanceof Class and
and not this instanceof EqualsMethod not this instanceof EqualsMethod and
and not this instanceof IEquatableEqualsMethod not this instanceof IEquatableEqualsMethod
} }
Type getType() { Type getType() { result = this.getParameter(0).getType() }
result = this.getParameter(0).getType()
}
} }
from EqualsOtherMethod equalsOther from EqualsOtherMethod equalsOther
where equalsOther.isSourceDeclaration() where
and not implementsEquals(equalsOther.getDeclaringType()) equalsOther.isSourceDeclaration() and
select equalsOther, "The $@ of this 'Equals(" + equalsOther.getType().getName() + ")' method does not override 'Equals(object)'.", not implementsEquals(equalsOther.getDeclaringType())
equalsOther.getDeclaringType(), "declaring type" select equalsOther,
"The $@ of this 'Equals(" + equalsOther.getType().getName() +
")' method does not override 'Equals(object)'.", equalsOther.getDeclaringType(),
"declaring type"

Просмотреть файл

@ -17,15 +17,16 @@ import Dispose
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
from DisposableType t, DisposableField f, Method dispose from DisposableType t, DisposableField f, Method dispose
where f.getDeclaringType() = t where
and not f.isStatic() f.getDeclaringType() = t and
and t.isSourceDeclaration() not f.isStatic() and
and dispose = getInvokedDisposeMethod(t) t.isSourceDeclaration() and
and dispose.getDeclaringType() = t dispose = getInvokedDisposeMethod(t) and
and not exists(MethodCall mc | dispose.getDeclaringType() = t and
mc.getTarget() instanceof DisposeMethod not exists(MethodCall mc |
and mc.getQualifier() = f.getAnAccess() mc.getTarget() instanceof DisposeMethod and
and mc.getEnclosingCallable() = dispose mc.getQualifier() = f.getAnAccess() and
mc.getEnclosingCallable() = dispose
) )
select dispose, "This 'Dispose()' method does not call 'Dispose()' on `IDisposable` field $@.", select dispose, "This 'Dispose()' method does not call 'Dispose()' on `IDisposable` field $@.", f,
f, f.getName() f.getName()

Просмотреть файл

@ -17,10 +17,10 @@ import Dispose
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
from DisposableType t, DisposableField f from DisposableType t, DisposableField f
where f.getDeclaringType() = t where
and t.isSourceDeclaration() f.getDeclaringType() = t and
and not f.isStatic() t.isSourceDeclaration() and
and not implementsDispose(t) not f.isStatic() and
and not isAutoDisposedWebControl(f) not implementsDispose(t) and
select t, "This type does not override 'Dispose()' but has disposable field $@.", not isAutoDisposedWebControl(f)
f, f.getName() select t, "This type does not override 'Dispose()' but has disposable field $@.", f, f.getName()

Просмотреть файл

@ -22,55 +22,57 @@ import semmle.code.csharp.commons.Disposal
/** Holds if expression `e` escapes the local method scope. */ /** Holds if expression `e` escapes the local method scope. */
predicate escapes(Expr e) { predicate escapes(Expr e) {
// Things that return escape // 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 // Things that are assigned to fields, properties, or indexers escape the scope
exists(AssignableDefinition def, Assignable a | exists(AssignableDefinition def, Assignable a |
def.getSource() = e and def.getSource() = e and
a = def.getTarget() | a = def.getTarget()
|
a instanceof Field or a instanceof Field or
a instanceof Property or a instanceof Property or
a instanceof Indexer 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. */ /** Holds if the `disposable` is a whitelisted result. */
predicate isWhitelisted(LocalScopeDisposableCreation disposable) { predicate isWhitelisted(LocalScopeDisposableCreation disposable) {
exists(MethodCall mc | exists(MethodCall mc |
// Close can often be used instead of Dispose // Close can often be used instead of Dispose
mc.getTarget().hasName("Close") or mc.getTarget().hasName("Close")
or
// Used as an alias for Dispose // Used as an alias for Dispose
mc.getTarget().hasName("Clear") mc.getTarget().hasName("Clear")
| |
mc.getQualifier() = disposable.getADisposeTarget() mc.getQualifier() = disposable.getADisposeTarget()
) or )
or
// WebControls are usually disposed automatically // WebControls are usually disposed automatically
disposable.getType() instanceof WebControl disposable.getType() instanceof WebControl
} }
from LocalScopeDisposableCreation disposable from LocalScopeDisposableCreation disposable
// The disposable is local scope - the lifetime is the execution of this method // The disposable is local scope - the lifetime is the execution of this method
where not escapes(disposable.getADisposeTarget()) where
not escapes(disposable.getADisposeTarget()) and
// Only care about library types - user types often have spurious IDisposable declarations // 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 // 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 // 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 // As are disposables on which the Dispose method is called explicitly
and not exists(MethodCall mc | not exists(MethodCall mc |
mc.getTarget() instanceof DisposeMethod mc.getTarget() instanceof DisposeMethod and
and mc.getQualifier() = disposable.getADisposeTarget() mc.getQualifier() = disposable.getADisposeTarget()
) ) and
// Ignore whitelisted results // Ignore whitelisted results
and not isWhitelisted(disposable) not isWhitelisted(disposable) and
// Not passed to a disposing method // Not passed to a disposing method
and not exists(Call c, Parameter p | not exists(Call c, Parameter p | disposable.getADisposeTarget() = c.getArgumentForParameter(p) |
disposable.getADisposeTarget() = c.getArgumentForParameter(p) |
mayBeDisposed(p) mayBeDisposed(p)
) )
select disposable, "Disposable '" + disposable.getType() + "' is created here but is not disposed." select disposable, "Disposable '" + disposable.getType() + "' is created here but is not disposed."

Просмотреть файл

@ -21,23 +21,24 @@ private predicate potentialOverride(Method vm, Method m) {
* but does not do so. * but does not do so.
*/ */
predicate nonOverridingMethod(Method m, Method vm) { predicate nonOverridingMethod(Method m, Method vm) {
vm.isVirtual() vm.isVirtual() and
and not vm.isOverride() not vm.isOverride() and
and not vm.overrides() not vm.overrides() and
and potentialOverride(vm, m) potentialOverride(vm, m) and
and not m.overrides() not m.overrides() and
and not m.isOverride() not m.isOverride() and
and not m.isNew() not m.isNew() and
and m=m.getSourceDeclaration() m = m.getSourceDeclaration() and
and m.getNumberOfParameters() = vm.getNumberOfParameters() m.getNumberOfParameters() = vm.getNumberOfParameters() and
and forall(int i, Parameter p1, Parameter p2 | forall(int i, Parameter p1, Parameter p2 | p1 = m.getParameter(i) and p2 = vm.getParameter(i) |
p1=m.getParameter(i) and p2=vm.getParameter(i) | p1.getType() = p2.getType()
p1.getType() = p2.getType()) ) and
and m.getName().toLowerCase() = vm.getName().toLowerCase() m.getName().toLowerCase() = vm.getName().toLowerCase()
} }
from Method m, Method vm from Method m, Method vm
where m.fromSource() where
and nonOverridingMethod(m, vm) m.fromSource() and
nonOverridingMethod(m, vm)
select m, "Method '" + m.getName() + "' looks like it should override $@ but does not do so.", select m, "Method '" + m.getName() + "' looks like it should override $@ but does not do so.",
vm.getSourceDeclaration(), vm.getQualifiedName() vm.getSourceDeclaration(), vm.getQualifiedName()

Просмотреть файл

@ -14,7 +14,8 @@ import csharp
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
from MethodCall c, EqualsMethod equals from MethodCall c, EqualsMethod equals
where c.getTarget().getSourceDeclaration() = equals where
and c.getArgument(0) instanceof NullLiteral c.getTarget().getSourceDeclaration() = equals and
and not c.getQualifier().getType() instanceof NullableType 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'." select c, "Equality test with 'null' will never be true, but may throw a 'NullReferenceException'."

Просмотреть файл

@ -12,19 +12,18 @@
* statistical * statistical
* non-attributable * non-attributable
*/ */
import csharp import csharp
import semmle.code.csharp.frameworks.system.IO import semmle.code.csharp.frameworks.system.IO
import semmle.code.csharp.Chaining import semmle.code.csharp.Chaining
/** Holds if `m` is a method whose return value should always be checked. */ /** Holds if `m` is a method whose return value should always be checked. */
predicate important(Method m) { predicate important(Method m) {
exists(Method read | exists(Method read | read = any(SystemIOStreamClass c).getReadMethod() |
read = any(SystemIOStreamClass c).getReadMethod() |
m = read.getAnOverrider*() m = read.getAnOverrider*()
) )
or or
exists(Method readByte | exists(Method readByte | readByte = any(SystemIOStreamClass c).getReadByteMethod() |
readByte = any(SystemIOStreamClass c).getReadByteMethod() |
m = readByte.getAnOverrider*() m = readByte.getAnOverrider*()
) )
// add more ... // add more ...
@ -49,14 +48,14 @@ predicate dubious(Method m, int percentage) {
exists(int used, int total, Method target | exists(int used, int total, Method target |
target = m.getSourceDeclaration() and target = m.getSourceDeclaration() and
used = count(MethodCall mc | used = count(MethodCall mc |
mc.getTarget().getSourceDeclaration() = target and mc.getTarget().getSourceDeclaration() = target and
not mc instanceof DiscardedMethodCall and not mc instanceof DiscardedMethodCall and
(methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType()) (methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType())
) and ) and
total = count(MethodCall mc | total = count(MethodCall mc |
mc.getTarget().getSourceDeclaration() = target and mc.getTarget().getSourceDeclaration() = target and
(methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType()) (methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType())
) and ) and
used != total and used != total and
percentage = used * 100 / total and percentage = used * 100 / total and
percentage >= 90 and percentage >= 90 and
@ -66,9 +65,9 @@ predicate dubious(Method m, int percentage) {
int chainedUses(Method m) { int chainedUses(Method m) {
result = count(MethodCall mc, MethodCall qual | result = count(MethodCall mc, MethodCall qual |
m = mc.getTarget() and m = mc.getTarget() and
hasQualifierAndTarget(mc, qual, qual.getTarget()) hasQualifierAndTarget(mc, qual, qual.getTarget())
) )
} }
predicate hasQualifierAndTarget(MethodCall mc, Expr qualifier, Method m) { 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. */ /** Holds if `m` is a white-listed method where checking the return value is not required. */
predicate whitelist(Method m) { predicate whitelist(Method m) {
m.hasName("TryGetValue") or m.hasName("TryGetValue")
m.hasName("TryParse") or or
exists(Namespace n | m.hasName("TryParse")
n = m.getDeclaringType().getNamespace().getParentNamespace*() | or
exists(Namespace n | n = m.getDeclaringType().getNamespace().getParentNamespace*() |
n.getName().regexpMatch("(Fluent)?NHibernate") or n.getName().regexpMatch("(Fluent)?NHibernate") or
n.getName() = "Moq" n.getName() = "Moq"
) )
@ -89,9 +89,7 @@ predicate whitelist(Method m) {
} }
class DiscardedMethodCall extends MethodCall { class DiscardedMethodCall extends MethodCall {
DiscardedMethodCall() { DiscardedMethodCall() { this.getParent() instanceof ExprStmt }
this.getParent() instanceof ExprStmt
}
string query() { string query() {
exists(Method m | exists(Method m |
@ -99,11 +97,11 @@ class DiscardedMethodCall extends MethodCall {
not whitelist(m) and not whitelist(m) and
// Do not alert on "void wrapper methods", i.e., methods that are inserted // Do not alert on "void wrapper methods", i.e., methods that are inserted
// to deliberately ignore the returned value // to deliberately ignore the returned value
not getEnclosingCallable().getStatementBody().getNumberOfStmts() = 1 | not getEnclosingCallable().getStatementBody().getNumberOfStmts() = 1
|
(important(m) and result = "should always be checked") (important(m) and result = "should always be checked")
or or
exists(int percentage | exists(int percentage | dubious(m, percentage) |
dubious(m, percentage) |
result = percentage.toString() + "% of calls to this method have their result used" result = percentage.toString() + "% of calls to this method have their result used"
) )
) )

Просмотреть файл

@ -12,6 +12,5 @@
import semmle.code.asp.AspNet import semmle.code.asp.AspNet
from AspText text from AspText text
where where exists(text.getBody().regexpFind("\\w{3,}", _, _))
exists(text.getBody().regexpFind("\\w{3,}", _, _))
select text, "This text has not been internationalized." select text, "This text has not been internationalized."

Просмотреть файл

@ -12,6 +12,5 @@
import semmle.code.asp.AspNet import semmle.code.asp.AspNet
from AspCode code from AspCode code
where where exists(code.getBody().regexpFind("(Then|\\{)\\s*$", _, _))
exists(code.getBody().regexpFind("(Then|\\{)\\s*$",_,_))
select code, "Split control structure." select code, "Split control structure."

Просмотреть файл

@ -14,8 +14,7 @@ class SuppressionComment extends SinglelineComment {
string annotation; string annotation;
SuppressionComment() { SuppressionComment() {
exists(string text | exists(string text | text = this.getText() |
text = this.getText() |
// match `lgtm[...]` anywhere in the comment // match `lgtm[...]` anywhere in the comment
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _) annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
or or
@ -25,57 +24,49 @@ class SuppressionComment extends SinglelineComment {
} }
/** Gets the suppression annotation in this comment. */ /** Gets the suppression annotation in this comment. */
string getAnnotation() { string getAnnotation() { result = annotation }
result = annotation
}
/** /**
* Holds if this comment applies to the range from column `startcolumn` of line `startline` * Holds if this comment applies to the range from column `startcolumn` of line `startline`
* to column `endcolumn` of line `endline` in file `filepath`. * to column `endcolumn` of line `endline` in file `filepath`.
*/ */
predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) { predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
startcolumn = 1 startcolumn = 1
} }
/** Gets the scope of this suppression. */ /** Gets the scope of this suppression. */
SuppressionScope getScope() { SuppressionScope getScope() { this = result.getSuppressionComment() }
this = result.getSuppressionComment()
}
} }
/** /**
* The scope of an alert suppression comment. * The scope of an alert suppression comment.
*/ */
class SuppressionScope extends @commentline { class SuppressionScope extends @commentline {
SuppressionScope() { SuppressionScope() { this instanceof SuppressionComment }
this instanceof SuppressionComment
}
/** Gets a suppression comment with this scope. */ /** Gets a suppression comment with this scope. */
SuppressionComment getSuppressionComment() { SuppressionComment getSuppressionComment() { result = this }
result = this
}
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to * The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`. * column `endcolumn` of line `endline` in file `filepath`.
* For more information, see * For more information, see
* [LGTM locations](https://lgtm.com/help/ql/locations). * [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
) {
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn) this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
} }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
string toString() { string toString() { result = "suppression range" }
result = "suppression range"
}
} }
from SuppressionComment c from SuppressionComment c
select c, // suppression comment select c, // suppression comment
c.getText(), // text of suppression comment (excluding delimiters) c.getText(), // text of suppression comment (excluding delimiters)
c.getAnnotation(), // text of suppression annotation c.getAnnotation(), // text of suppression annotation
c.getScope() // scope of suppression c.getScope() // scope of suppression

Просмотреть файл

@ -15,32 +15,27 @@ import semmle.code.csharp.metrics.Coupling
/** inner is nested (possibly more than one level deep) within outer */ /** inner is nested (possibly more than one level deep) within outer */
predicate nestedWithin(ValueOrRefType outer, NestedType inner) { predicate nestedWithin(ValueOrRefType outer, NestedType inner) {
inner.getDeclaringType() = outer inner.getDeclaringType() = outer or
or nestedWithin(outer, inner.getDeclaringType()) nestedWithin(outer, inner.getDeclaringType())
} }
from ValueOrRefType t1, ValueOrRefType t2 from ValueOrRefType t1, ValueOrRefType t2
where where
t1 != t2 t1 != t2 and
and depends(t1, t2) depends(t1, t2) and
and depends(t2, t1) depends(t2, t1) and
// PREVENT SYMMETRICAL RESULTS // PREVENT SYMMETRICAL RESULTS
and t1.getName() < t2.getName() t1.getName() < t2.getName() and
// ADDITIONAL CONSTRAINTS // ADDITIONAL CONSTRAINTS
and t1.fromSource() t1.fromSource() and
and t2.fromSource() t2.fromSource() and
// EXCLUSIONS // EXCLUSIONS
and not not (
( nestedWithin(t1, t2) or
nestedWithin(t1, t2) nestedWithin(t2, t1) or
or nestedWithin(t2, t1) t1.getName().toLowerCase().matches("%visitor%") or
or t1.getName().toLowerCase().matches("%visitor%") t2.getName().toLowerCase().matches("%visitor%") or
or t2.getName().toLowerCase().matches("%visitor%") t1.getAMember().getName().toLowerCase().matches("%visit%") or
or t1.getAMember().getName().toLowerCase().matches("%visit%") t2.getAMember().getName().toLowerCase().matches("%visit%")
or t2.getAMember().getName().toLowerCase().matches("%visit%")
) )
select t1, "This type and type $@ are mutually dependent.", select t1, "This type and type $@ are mutually dependent.", t2, t2.getName()
t2, t2.getName()

Просмотреть файл

@ -11,31 +11,24 @@
* maintainability * maintainability
* modularity * modularity
*/ */
import csharp import csharp
Member getAUsedMember(Method m) { Member getAUsedMember(Method m) {
exists(MemberAccess ma | exists(MemberAccess ma | ma.getEnclosingCallable() = m |
ma.getEnclosingCallable() = m |
result = ma.getTarget().getSourceDeclaration() result = ma.getTarget().getSourceDeclaration()
) )
or or
exists(Call c | exists(Call c | c.getEnclosingCallable() = m | result = c.getTarget().getSourceDeclaration())
c.getEnclosingCallable() = m |
result = c.getTarget().getSourceDeclaration()
)
} }
int dependencyCount(Method source, RefType target) { int dependencyCount(Method source, RefType target) {
result = strictcount(Member m | m = getAUsedMember(source) and m = target.getAMember()) result = strictcount(Member m | m = getAUsedMember(source) and m = target.getAMember())
} }
predicate methodDependsOn(Method m, RefType target) { predicate methodDependsOn(Method m, RefType target) { exists(dependencyCount(m, target)) }
exists(dependencyCount(m, target))
}
predicate dependsOn(RefType source, RefType target) { predicate dependsOn(RefType source, RefType target) { methodDependsOn(source.getAMethod(), target) }
methodDependsOn(source.getAMethod(), target)
}
int selfDependencyCount(Method source) { int selfDependencyCount(Method source) {
result = sum(dependencyCount(source, source.getDeclaringType+())) result = sum(dependencyCount(source, source.getDeclaringType+()))
@ -44,12 +37,12 @@ int selfDependencyCount(Method source) {
predicate dependsHighlyOn(Method source, RefType target, int selfCount, int depCount) { predicate dependsHighlyOn(Method source, RefType target, int selfCount, int depCount) {
depCount = dependencyCount(source, target) and depCount = dependencyCount(source, target) and
selfCount = selfDependencyCount(source) and selfCount = selfDependencyCount(source) and
depCount > 2*selfCount and depCount > 2 * selfCount and
depCount > 4 depCount > 4
} }
predicate query(Method m, RefType targetType, int selfCount, int depCount) { 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 dependsHighlyOn(m, targetType, selfCount, depCount) and
// Interfaces are depended upon by their very nature // Interfaces are depended upon by their very nature
not targetType instanceof Interface and 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 // Do not move between nested types
not (sourceType.getDeclaringType*() = targetType or targetType.getDeclaringType*() = sourceType) and not (sourceType.getDeclaringType*() = targetType or targetType.getDeclaringType*() = sourceType) and
// Check that the target type already depends on every type used by the method // Check that the target type already depends on every type used by the method
forall(RefType dependency | forall(RefType dependency | methodDependsOn(m, dependency) |
methodDependsOn(m, dependency) |
dependsOn(targetType, dependency) or dependsOn(targetType, dependency) or
targetType = dependency or targetType = dependency or
dependency.getNamespace().hasName("System") 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 from Method m, RefType other, int selfCount, int depCount
where query(m, other, selfCount, depCount) and where
// Don't include types that are used from many different places - we only highlight query(m, other, selfCount, depCount) and
// relatively local fixes that could reasonably be implemented. // Don't include types that are used from many different places - we only highlight
count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10 // relatively local fixes that could reasonably be implemented.
select m, "Method " + m.getName() + " is too closely tied to $@: " + depCount + count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10
" dependencies to it, but only " + selfCount + " dependencies to its own type.", select m,
other, other.getName() "Method " + m.getName() + " is too closely tied to $@: " + depCount +
" dependencies to it, but only " + selfCount + " dependencies to its own type.", other,
other.getName()

Просмотреть файл

@ -9,6 +9,7 @@
* @tags maintainability * @tags maintainability
* modularity * modularity
*/ */
import csharp import csharp
predicate enclosingRefType(Variable v, RefType type) { predicate enclosingRefType(Variable v, RefType type) {
@ -45,16 +46,19 @@ predicate dependencyCount(RefType source, RefType target, int res) {
exists(int varCount, int funCount | exists(int varCount, int funCount |
variableDependencyCount(source, target, varCount) and variableDependencyCount(source, target, varCount) and
functionDependencyCount(source, target, funCount) and functionDependencyCount(source, target, funCount) and
res = varCount + funCount res = varCount + funCount and
and res > 15) res > 15
)
} }
from RefType a, RefType b, int ca, int cb from RefType a, RefType b, int ca, int cb
where dependencyCount(a, b, ca) and where
dependencyCount(b, a, cb) and dependencyCount(a, b, ca) and
ca > 15 and dependencyCount(b, a, cb) and
cb > 15 and ca > 15 and
ca >= cb and cb > 15 and
a != b ca >= cb and
select a, "Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() + a != b
" dependencies one way and " + cb.toString() + " the other).", b, b.getName() select a,
"Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() +
" dependencies one way and " + cb.toString() + " the other).", b, b.getName()

Просмотреть файл

@ -12,7 +12,8 @@
import csharp import csharp
from Class c, Method m, MethodCall call from Class c, Method m, MethodCall call
where m.isExtern() where
and m.getDeclaringType() = c m.isExtern() and
and call.getTarget() = m m.getDeclaringType() = c and
call.getTarget() = m
select call, "Replace this call with a call to managed code if possible." select call, "Replace this call with a call to managed code if possible."

Просмотреть файл

@ -9,6 +9,7 @@
* correctness * correctness
* external/cwe/cwe-395 * external/cwe/cwe-395
*/ */
import csharp import csharp
from SpecificCatchClause scc from SpecificCatchClause scc

Просмотреть файл

@ -12,12 +12,10 @@
import csharp import csharp
class CommentedOutCode extends CommentBlock class CommentedOutCode extends CommentBlock {
{ CommentedOutCode() {
CommentedOutCode()
{
not isXmlCommentBlock() and not isXmlCommentBlock() and
2*count(getAProbableCodeLine()) > count(getANonEmptyLine()) 2 * count(getAProbableCodeLine()) > count(getANonEmptyLine())
} }
} }

Просмотреть файл

@ -9,6 +9,7 @@
* @tags maintainability * @tags maintainability
* external/cwe/cwe-546 * external/cwe/cwe-546
*/ */
import csharp import csharp
from CommentLine c from CommentLine c

Просмотреть файл

@ -11,6 +11,7 @@
* readability * readability
* external/cwe/cwe-835 * external/cwe/cwe-835
*/ */
import csharp import csharp
import semmle.code.csharp.commons.Assertions import semmle.code.csharp.commons.Assertions
import semmle.code.csharp.commons.Constants import semmle.code.csharp.commons.Constants
@ -28,13 +29,9 @@ abstract class ConstantCondition extends Expr {
class ConstantBooleanCondition extends ConstantCondition { class ConstantBooleanCondition extends ConstantCondition {
boolean b; boolean b;
ConstantBooleanCondition() { ConstantBooleanCondition() { isConstantCondition(this, b) }
isConstantCondition(this, b)
}
override string getMessage() { override string getMessage() { result = "Condition always evaluates to '" + b + "'." }
result = "Condition always evaluates to '" + b + "'."
}
override predicate isWhiteListed() { override predicate isWhiteListed() {
// E.g. `x ?? false` // E.g. `x ?? false`
@ -60,9 +57,7 @@ class ConstantIfCondition extends ConstantBooleanCondition {
/** A constant loop condition. */ /** A constant loop condition. */
class ConstantLoopCondition extends ConstantBooleanCondition { class ConstantLoopCondition extends ConstantBooleanCondition {
ConstantLoopCondition() { ConstantLoopCondition() { this = any(LoopStmt ls).getCondition() }
this = any(LoopStmt ls).getCondition()
}
override predicate isWhiteListed() { override predicate isWhiteListed() {
// Clearly intentional infinite loops are allowed // Clearly intentional infinite loops are allowed
@ -75,10 +70,8 @@ class ConstantNullnessCondition extends ConstantCondition {
boolean b; boolean b;
ConstantNullnessCondition() { ConstantNullnessCondition() {
forex(ControlFlow::Node cfn | forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() |
cfn = this.getAControlFlowNode() | exists(ControlFlow::SuccessorTypes::NullnessSuccessor t | exists(cfn.getASuccessorByType(t)) |
exists(ControlFlow::SuccessorTypes::NullnessSuccessor t |
exists(cfn.getASuccessorByType(t)) |
b = t.getValue() b = t.getValue()
) and ) and
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1 strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
@ -86,10 +79,9 @@ class ConstantNullnessCondition extends ConstantCondition {
} }
override string getMessage() { override string getMessage() {
if b = true then if b = true
result = "Expression is always 'null'." then result = "Expression is always 'null'."
else else result = "Expression is never 'null'."
result = "Expression is never 'null'."
} }
} }
@ -98,10 +90,8 @@ class ConstantMatchingCondition extends ConstantCondition {
boolean b; boolean b;
ConstantMatchingCondition() { ConstantMatchingCondition() {
forex(ControlFlow::Node cfn | forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() |
cfn = this.getAControlFlowNode() | exists(ControlFlow::SuccessorTypes::MatchingSuccessor t | exists(cfn.getASuccessorByType(t)) |
exists(ControlFlow::SuccessorTypes::MatchingSuccessor t |
exists(cfn.getASuccessorByType(t)) |
b = t.getValue() b = t.getValue()
) and ) and
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1 strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
@ -109,15 +99,13 @@ class ConstantMatchingCondition extends ConstantCondition {
} }
override string getMessage() { override string getMessage() {
if b = true then if b = true then result = "Pattern always matches." else result = "Pattern never matches."
result = "Pattern always matches."
else
result = "Pattern never matches."
} }
} }
from ConstantCondition c, string msg from ConstantCondition c, string msg
where msg = c.getMessage() where
and not c.isWhiteListed() msg = c.getMessage() and
and not isExprInAssertion(c) not c.isWhiteListed() and
not isExprInAssertion(c)
select c, msg select c, msg

Просмотреть файл

@ -13,7 +13,8 @@
import csharp import csharp
from Interface i from Interface i
where not exists(i.getAMember()) where
and i.isSourceDeclaration() not exists(i.getAMember()) and
and count(Interface base | i.getABaseInterface() = base) <= 1 i.isSourceDeclaration() and
count(Interface base | i.getABaseInterface() = base) <= 1
select i, "Interface '" + i.getName() + "' does not declare any members." select i, "Interface '" + i.getName() + "' does not declare any members."

Просмотреть файл

@ -9,9 +9,10 @@
* @tags maintainability * @tags maintainability
* readability * readability
*/ */
import csharp import csharp
pragma [noinline] pragma[noinline]
private string localVarInType(ValueOrRefType t, LocalScopeVariable v) { private string localVarInType(ValueOrRefType t, LocalScopeVariable v) {
v.getCallable().getDeclaringType() = t and v.getCallable().getDeclaringType() = t and
result = v.getName() and result = v.getName() and
@ -28,12 +29,10 @@ private string memberInType(ValueOrRefType t, Member m) {
} }
private predicate acceptableShadowing(LocalScopeVariable v, Member m) { private predicate acceptableShadowing(LocalScopeVariable v, Member m) {
exists(ValueOrRefType t | exists(ValueOrRefType t | localVarInType(t, v) = memberInType(t, m) |
localVarInType(t, v) = memberInType(t, m) |
// If the callable declaring the local also accesses the shadowed member // If the callable declaring the local also accesses the shadowed member
// using an explicit `this` qualifier, the shadowing is likely deliberate. // using an explicit `this` qualifier, the shadowing is likely deliberate.
exists(MemberAccess ma | exists(MemberAccess ma | ma.getTarget() = m |
ma.getTarget() = m |
ma.getEnclosingCallable() = v.getCallable() and ma.getEnclosingCallable() = v.getCallable() and
ma.targetIsLocalInstance() and ma.targetIsLocalInstance() and
not ma.getQualifier().isImplicit() 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 from LocalScopeVariable v, Callable c, ValueOrRefType t, Member m
where c = v.getCallable() where
and shadowing(t, v, m) c = v.getCallable() and
and (c.(Modifiable).isStatic() implies m.isStatic()) shadowing(t, v, m) and
select v, "Local scope variable '" + v.getName() + "' shadows $@.", m, t.getName() + "." + m.getName() (c.(Modifiable).isStatic() implies m.isStatic())
select v, "Local scope variable '" + v.getName() + "' shadows $@.", m,
t.getName() + "." + m.getName()

Просмотреть файл

@ -9,6 +9,7 @@
* @tags maintainability * @tags maintainability
* modularity * modularity
*/ */
import csharp import csharp
class ConstantField extends Field { class ConstantField extends Field {
@ -20,11 +21,11 @@ class ConstantField extends Field {
} }
from Class c from Class c
where c.isSourceDeclaration() where
and c.isAbstract() c.isSourceDeclaration() and
and c.getAMember() instanceof ConstantField c.isAbstract() and
and forex(Member m | c.getAMember() instanceof ConstantField and
m = c.getAMember() | forex(Member m | m = c.getAMember() |
m instanceof ConstantField or m instanceof ConstantField or
m instanceof Constructor m instanceof Constructor
) )

Просмотреть файл

@ -13,7 +13,9 @@
import csharp import csharp
from Method m, int n from Method m, int n
where m.isSourceDeclaration() where
and n = count(Parameter p | p = m.getAParameter() and p.isRef()) m.isSourceDeclaration() and
and n > 2 n = count(Parameter p | p = m.getAParameter() and p.isRef()) and
select m, "Method '" + m.getName() + "' has " + n + " 'ref' parameters and might be hard to understand." n > 2
select m,
"Method '" + m.getName() + "' has " + n + " 'ref' parameters and might be hard to understand."

Просмотреть файл

@ -11,9 +11,11 @@
* external/cwe/cwe-390 * external/cwe/cwe-390
* external/cwe/cwe-391 * external/cwe/cwe-391
*/ */
import csharp import csharp
from CatchClause cc from CatchClause cc
where cc.getBlock().isEmpty() where
and not exists(CommentBlock cb | cb.getParent()=cc.getBlock()) cc.getBlock().isEmpty() and
not exists(CommentBlock cb | cb.getParent() = cc.getBlock())
select cc, "Poor error handling: empty catch block." select cc, "Poor error handling: empty catch block."

Просмотреть файл

@ -9,31 +9,28 @@
* correctness * correctness
* external/cwe/cwe-486 * external/cwe/cwe-486
*/ */
import csharp import csharp
import semmle.code.csharp.commons.ComparisonTest import semmle.code.csharp.commons.ComparisonTest
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
ComparisonTest getComparisonTest(Expr e) { ComparisonTest getComparisonTest(Expr e) { result.getExpr() = e }
result.getExpr() = e
}
class StringComparison extends Expr { class StringComparison extends Expr {
StringComparison() { StringComparison() {
exists(ComparisonTest ct | exists(ComparisonTest ct | ct = getComparisonTest(this) |
ct = getComparisonTest(this) |
ct.getComparisonKind().isEquality() and ct.getComparisonKind().isEquality() and
ct.getFirstArgument().stripCasts().getType() instanceof StringType and ct.getFirstArgument().stripCasts().getType() instanceof StringType and
ct.getSecondArgument().stripCasts().getType() instanceof StringType ct.getSecondArgument().stripCasts().getType() instanceof StringType
) )
} }
Expr getAnOperand() { Expr getAnOperand() { result = getComparisonTest(this).getAnArgument() }
result = getComparisonTest(this).getAnArgument()
}
} }
from StringComparison sc, PropertyAccess pa from StringComparison sc, PropertyAccess pa
where sc.getAnOperand() instanceof StringLiteral where
and sc.getAnOperand() = pa sc.getAnOperand() instanceof StringLiteral and
and pa.getTarget() = any(SystemTypeClass c).getFullNameProperty() sc.getAnOperand() = pa and
pa.getTarget() = any(SystemTypeClass c).getFullNameProperty()
select sc, "Erroneous class compare." select sc, "Erroneous class compare."

Просмотреть файл

@ -12,6 +12,7 @@
* modularity * modularity
* external/cwe/cwe-485 * external/cwe/cwe-485
*/ */
import csharp import csharp
import semmle.code.csharp.frameworks.system.Collections import semmle.code.csharp.frameworks.system.Collections
import semmle.code.csharp.frameworks.system.collections.Generic import semmle.code.csharp.frameworks.system.collections.Generic
@ -19,8 +20,7 @@ import semmle.code.csharp.frameworks.system.collections.Generic
/** A collection interface. */ /** A collection interface. */
class CollectionInterface extends Interface { class CollectionInterface extends Interface {
CollectionInterface() { CollectionInterface() {
exists(Interface i | exists(Interface i | i = this.getABaseInterface*() |
i = this.getABaseInterface*() |
i instanceof SystemCollectionsICollectionInterface or i instanceof SystemCollectionsICollectionInterface or
i.getSourceDeclaration() instanceof SystemCollectionsGenericICollectionInterface or i.getSourceDeclaration() instanceof SystemCollectionsGenericICollectionInterface or
i instanceof SystemCollectionsIEnumerableInterface or i instanceof SystemCollectionsIEnumerableInterface or
@ -30,8 +30,10 @@ class CollectionInterface extends Interface {
} }
from CastExpr e, Class c, CollectionInterface i from CastExpr e, Class c, CollectionInterface i
where e.getType() = c where
and e.getExpr().getType() = i e.getType() = c and
and c.isImplicitlyConvertibleTo(i) e.getExpr().getType() = i and
select e, "Questionable cast from abstract '" + i.getName() c.isImplicitlyConvertibleTo(i)
+ "' to concrete implementation '" + c.getName() + "'." select e,
"Questionable cast from abstract '" + i.getName() + "' to concrete implementation '" + c.getName()
+ "'."

Просмотреть файл

@ -9,6 +9,7 @@
* @tags reliability * @tags reliability
* external/cwe/cwe-485 * external/cwe/cwe-485
*/ */
import csharp import csharp
import semmle.code.csharp.commons.Collections import semmle.code.csharp.commons.Collections
import DataFlow import DataFlow
@ -31,13 +32,9 @@ predicate returnsCollection(Callable c, Field f) {
predicate mayWriteToCollection(Expr modified) { predicate mayWriteToCollection(Expr modified) {
modified instanceof CollectionModificationAccess modified instanceof CollectionModificationAccess
or or
exists(Expr mid | exists(Expr mid | mayWriteToCollection(mid) | localFlow(exprNode(modified), exprNode(mid)))
mayWriteToCollection(mid) |
localFlow(exprNode(modified), exprNode(mid))
)
or or
exists(MethodCall mid, Callable c | exists(MethodCall mid, Callable c | mayWriteToCollection(mid) |
mayWriteToCollection(mid) |
mid.getTarget() = c and mid.getTarget() = c and
c.canReturn(modified) c.canReturn(modified)
) )
@ -49,16 +46,12 @@ predicate modificationAfter(Expr before, Expr after) {
} }
VariableAccess varPassedInto(Callable c, Parameter p) { VariableAccess varPassedInto(Callable c, Parameter p) {
exists(Call call | exists(Call call | call.getTarget() = c | call.getArgumentForParameter(p) = result)
call.getTarget() = c |
call.getArgumentForParameter(p) = result
)
} }
predicate exposesByReturn(Callable c, Field f, Expr why, string whyText) { predicate exposesByReturn(Callable c, Field f, Expr why, string whyText) {
returnsCollection(c, f) and returnsCollection(c, f) and
exists(MethodCall ma | exists(MethodCall ma | ma.getTarget() = c |
ma.getTarget() = c |
mayWriteToCollection(ma) and mayWriteToCollection(ma) and
why = ma and why = ma and
whyText = "after this call to " + c.getName() 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 from Callable c, Field f, Expr why, string whyText
where exposesByReturn(c, f, why, whyText) or where
exposesByStore(c, f, why, whyText) exposesByReturn(c, f, why, whyText) or
select c, "'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() + exposesByStore(c, f, why, whyText)
"'. The value may be modified $@.", select c,
why.getLocation(), whyText "'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() +
"'. The value may be modified $@.", why.getLocation(), whyText

Просмотреть файл

@ -10,31 +10,32 @@
* modularity * modularity
* external/cwe/cwe-582 * external/cwe/cwe-582
*/ */
import csharp import csharp
predicate nonEmptyArrayLiteralOrNull(Expr e) { predicate nonEmptyArrayLiteralOrNull(Expr e) {
e = any(ArrayCreation arr | e = any(ArrayCreation arr |
exists(arr.getInitializer().getAnElement()) exists(arr.getInitializer().getAnElement())
or or
not arr.getALengthArgument().getValue() = "0" not arr.getALengthArgument().getValue() = "0"
) )
or or
e instanceof NullLiteral e instanceof NullLiteral
or or
e = any(ConditionalExpr cond | e = any(ConditionalExpr cond |
nonEmptyArrayLiteralOrNull(cond.getThen()) and nonEmptyArrayLiteralOrNull(cond.getThen()) and
nonEmptyArrayLiteralOrNull(cond.getElse()) nonEmptyArrayLiteralOrNull(cond.getElse())
) )
} }
from Field f from Field f
where f.isPublic() where
and f.isStatic() f.isPublic() and
and f.isReadOnly() f.isStatic() and
and f.getType() instanceof ArrayType f.isReadOnly() and
and f.fromSource() f.getType() instanceof ArrayType and
and forall(AssignableDefinition def | f.fromSource() and
def.getTarget() = f | forall(AssignableDefinition def | def.getTarget() = f |
nonEmptyArrayLiteralOrNull(def.getSource()) nonEmptyArrayLiteralOrNull(def.getSource())
) )
select f, "The array constant '" + f.getName() + "' is vulnerable to mutation." select f, "The array constant '" + f.getName() + "' is vulnerable to mutation."

Просмотреть файл

@ -10,11 +10,15 @@
* frameworks/asp.net * frameworks/asp.net
* external/cwe/cwe-489 * external/cwe/cwe-489
*/ */
import csharp import csharp
import semmle.code.csharp.commons.Util import semmle.code.csharp.commons.Util
from MainMethod m from MainMethod m
where m.fromSource() where
and exists(UsingNamespaceDirective u | u.getFile() = m.getFile() m.fromSource() and
and u.getImportedNamespace().hasQualifiedName("System.Web")) 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." select m, "Remove debug code if your ASP.NET application is in production."

Просмотреть файл

@ -8,15 +8,15 @@
* @tags changeability * @tags changeability
* maintainability * maintainability
*/ */
import csharp import csharp
import MagicConstants import MagicConstants
predicate selection(Element e, string msg) { predicate selection(Element e, string msg) { magicConstant(e, msg) }
magicConstant(e, msg)
}
from Literal e, string msg from Literal e, string msg
where selection(e, msg) where
and isNumber(e) selection(e, msg) and
and not exists(Field f | f.getInitializer() = e) isNumber(e) and
not exists(Field f | f.getInitializer() = e)
select e, msg select e, msg

Просмотреть файл

@ -11,9 +11,7 @@
import MagicConstants import MagicConstants
predicate selection(Element e, string msg) { predicate selection(Element e, string msg) { magicConstant(e, msg) }
magicConstant(e, msg)
}
from StringLiteral e, string msg from StringLiteral e, string msg
where selection(e, msg) where selection(e, msg)

Просмотреть файл

@ -12,6 +12,7 @@
import MagicConstants import MagicConstants
from Literal magicLiteral, string message, Field constant from Literal magicLiteral, string message, Field constant
where isNumber(magicLiteral) where
and literalInsteadOfConstant(magicLiteral, _, message, constant) isNumber(magicLiteral) and
literalInsteadOfConstant(magicLiteral, _, message, constant)
select magicLiteral, message, constant, constant.getName() select magicLiteral, message, constant, constant.getName()

Просмотреть файл

@ -9,6 +9,7 @@
* readability * readability
* naming * naming
*/ */
import csharp import csharp
predicate typeWithConfusingName(ValueOrRefType type) { predicate typeWithConfusingName(ValueOrRefType type) {
@ -16,11 +17,12 @@ predicate typeWithConfusingName(ValueOrRefType type) {
} }
from Method m, Method n, ValueOrRefType type from Method m, Method n, ValueOrRefType type
where typeWithConfusingName(type) where
and type.fromSource() typeWithConfusingName(type) and
and m = type.getAMethod() type.fromSource() and
and n = type.getAMethod() m = type.getAMethod() and
and m != n n = type.getAMethod() and
and m.getName().toLowerCase() = n.getName().toLowerCase() m != n and
and m.getName() < n.getName() m.getName().toLowerCase() = n.getName().toLowerCase() and
m.getName() < n.getName()
select m, "Confusing method name, compare with $@.", n, n.getName() select m, "Confusing method name, compare with $@.", n, n.getName()

Просмотреть файл

@ -10,15 +10,18 @@
* readability * readability
* naming * naming
*/ */
import csharp import csharp
predicate hasSubtypeStar(RefType t, RefType u) { predicate hasSubtypeStar(RefType t, RefType u) {
t = u t = u or
or u.getABaseType+() = t 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) { predicate methodNames(RefType t, Method m, string lowercase) {
exists(RefType t2 | exists(RefType t2 |
m.getDeclaringType() = t2 and m.getDeclaringType() = t2 and
@ -28,8 +31,10 @@ predicate methodNames(RefType t, Method m, string lowercase) {
lowercase.length() > 1 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) { predicate confusing(Method m1, Method m2) {
exists(RefType t, string lower | exists(RefType t, string lower |
methodNames(t, m1, lower) and 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. * Two method names are confusing if all of the following conditions hold:
* They are not declared in the same class, and the superclass method is * They are both static methods or both instance methods.
* not overridden in an intermediate class * They are not declared in the same class, and the superclass method is
* They have different names. * not overridden in an intermediate class
* They have the same names if case is ignored. * They have different names.
* There is no method in the subclass that has the same name as * They have the same names if case is ignored.
* the superclass method * There is no method in the subclass that has the same name as
There is an additional check that only methods with names longer than one character * the superclass method
can be considered confusing. */ * There is an additional check that only methods with names longer than one character
* can be considered confusing.
*/
from Method m1, Method m2 from Method m1, Method m2
where confusing(m1,m2) and where
m1.getDeclaringType() != m2.getDeclaringType() and confusing(m1, m2) and
( m1.getDeclaringType() != m2.getDeclaringType() and
m1.isStatic() and m2.isStatic() (
or m1.isStatic() and m2.isStatic()
not m1.isStatic() and not m2.isStatic() or
) and not m1.isStatic() and not m2.isStatic()
not exists(Method mid | ) and
confusing(m1, mid) and not exists(Method mid |
mid.getDeclaringType().getABaseType+() = m2.getDeclaringType() confusing(m1, mid) and
) and mid.getDeclaringType().getABaseType+() = m2.getDeclaringType()
not exists(Method notConfusing | ) and
notConfusing.getDeclaringType() = m1.getDeclaringType() and not exists(Method notConfusing |
notConfusing.getName() = m2.getName() notConfusing.getDeclaringType() = m1.getDeclaringType() and
) and notConfusing.getName() = m2.getName()
m1.fromSource() ) and
select m1, "confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " m1.fromSource()
+ m2.getName() + " in " + m2.getDeclaringType().getName() + "." select m1,
"confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " +
m2.getName() + " in " + m2.getDeclaringType().getName() + "."

Просмотреть файл

@ -23,13 +23,12 @@ class PublicConstantField extends Field {
from PublicConstantField f from PublicConstantField f
where where
// The first character of the field's name is not uppercase. // The first character of the field's name is not uppercase.
not(f.getName().charAt(0).isUppercase()) not (f.getName().charAt(0).isUppercase())
or or
( (
// The field's name is uppercase. // The field's name is uppercase.
f.getName().isUppercase() f.getName().isUppercase() and
// The field's name is at least 4 characters long. // 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." select f, "Public static read-only fields should be named in PascalCase."

Просмотреть файл

@ -12,51 +12,89 @@
import csharp import csharp
string prefix(string typename) { string prefix(string typename) {
(typename = "System.Web.UI.WebControls.Label" and result = "lbl") or (typename = "System.Web.UI.WebControls.Label" and result = "lbl")
(typename = "System.Web.UI.WebControls.TextBox" and result = "txt") or or
(typename = "System.Web.UI.WebControls.Button" and result = "btn") or (typename = "System.Web.UI.WebControls.TextBox" and result = "txt")
(typename = "System.Web.UI.WebControls.LinkButton" and result = "btn") or or
(typename = "System.Web.UI.WebControls.ImageButton" and result = "ibtn") or (typename = "System.Web.UI.WebControls.Button" and result = "btn")
(typename = "System.Web.UI.WebControls.Hyperlink" and result = "hpl") or or
(typename = "System.Web.UI.WebControls.DropDownList" and result = "cmb") or (typename = "System.Web.UI.WebControls.LinkButton" and result = "btn")
(typename = "System.Web.UI.WebControls.ListBox" and result = "lst") or or
(typename = "System.Web.UI.WebControls.Datagrid" and result = "dgr") or (typename = "System.Web.UI.WebControls.ImageButton" and result = "ibtn")
(typename = "System.Web.UI.WebControls.Datalist" and result = "dtl") or or
(typename = "System.Web.UI.WebControls.Repeater" and result = "rpt") or (typename = "System.Web.UI.WebControls.Hyperlink" and result = "hpl")
(typename = "System.Web.UI.WebControls.CheckBox" and result = "chk") or or
(typename = "System.Web.UI.WebControls.CheckBoxList" and result = "chklst") or (typename = "System.Web.UI.WebControls.DropDownList" and result = "cmb")
(typename = "System.Web.UI.WebControls.RadioButtonList" and result = "radlst") or or
(typename = "System.Web.UI.WebControls.RadioButton" and result = "rad") or (typename = "System.Web.UI.WebControls.ListBox" and result = "lst")
(typename = "System.Web.UI.WebControls.Image" and result = "img") or or
(typename = "System.Web.UI.WebControls.Panel" and result = "pnl") or (typename = "System.Web.UI.WebControls.Datagrid" and result = "dgr")
(typename = "System.Web.UI.WebControls.PlaceHolder" and result = "plh") or or
(typename = "System.Web.UI.WebControls.Calendar" and result = "cal") or (typename = "System.Web.UI.WebControls.Datalist" and result = "dtl")
(typename = "System.Web.UI.WebControls.AdRotator" and result = "adr") or or
(typename = "System.Web.UI.WebControls.Table" and result = "tbl") or (typename = "System.Web.UI.WebControls.Repeater" and result = "rpt")
(typename = "System.Web.UI.WebControls.RequiredFieldValidator" and result = "rfv") or or
(typename = "System.Web.UI.WebControls.CompareValidator" and result = "cmv") or (typename = "System.Web.UI.WebControls.CheckBox" and result = "chk")
(typename = "System.Web.UI.WebControls.RegularExpressionValidator" and result = "rev") or or
(typename = "System.Web.UI.WebControls.CustomValidator" and result = "csv") or (typename = "System.Web.UI.WebControls.CheckBoxList" and result = "chklst")
(typename = "System.Web.UI.WebControls.ValidationSummary" and result = "vsm") or or
(typename = "System.Web.UI.WebControls.XML" and result = "xml") or (typename = "System.Web.UI.WebControls.RadioButtonList" and result = "radlst")
(typename = "System.Web.UI.WebControls.Literal" and result = "lit") or or
(typename = "System.Web.UI.WebControls.Form" and result = "frm") or (typename = "System.Web.UI.WebControls.RadioButton" and result = "rad")
(typename = "System.Web.UI.WebControls.Frame" and result = "fra") or or
(typename = "System.Web.UI.WebControls.CrystalReportViewer" and result = "crvr") or (typename = "System.Web.UI.WebControls.Image" and result = "img")
or
(typename = "System.Web.UI.HtmlControls.TextArea" and result = "txa") or (typename = "System.Web.UI.WebControls.Panel" and result = "pnl")
(typename = "System.Web.UI.HtmlControls.FileField" and result = "fle") or or
(typename = "System.Web.UI.HtmlControls.PasswordField" and result = "pwd") or (typename = "System.Web.UI.WebControls.PlaceHolder" and result = "plh")
(typename = "System.Web.UI.HtmlControls.Hidden" and result = "hdn") or or
(typename = "System.Web.UI.HtmlControls.Table" and result = "tbl") or (typename = "System.Web.UI.WebControls.Calendar" and result = "cal")
(typename = "System.Web.UI.HtmlControls.FlowLayoutPanel" and result = "flp") or or
(typename = "System.Web.UI.HtmlControls.GridLayoutPanel" and result = "glp") 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") (typename = "System.Web.UI.HtmlControls.HorizontalRule" and result = "hr")
} }
from Field f, RefType t, string name, string prefix from Field f, RefType t, string name, string prefix
where f.getType() = t where
and f.getName() = name f.getType() = t and
and prefix = prefix(t.getQualifiedName()) f.getName() = name and
and not name.matches(prefix + "%") prefix = prefix(t.getQualifiedName()) and
not name.matches(prefix + "%")
select f, "This field should have the prefix '" + prefix + "' to match its types." select f, "This field should have the prefix '" + prefix + "' to match its types."

Просмотреть файл

@ -1,7 +1,7 @@
/** /**
* @name Windows controls with generated names * @name Windows controls with generated names
* @description Replacing the generated names in windows forms with meaningful 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 * @kind problem
* @problem.severity recommendation * @problem.severity recommendation
* @precision medium * @precision medium
@ -9,10 +9,10 @@
* @tags readability * @tags readability
* naming * naming
*/ */
import csharp import csharp
predicate controlName(string prefix) predicate controlName(string prefix) {
{
prefix = "[Ll]abel" or prefix = "[Ll]abel" or
prefix = "[Bb]utton" or prefix = "[Bb]utton" or
prefix = "[Pp]anel" or prefix = "[Pp]anel" or
@ -28,13 +28,15 @@ predicate controlName(string prefix)
predicate usedInHumanWrittenCode(Field f) { predicate usedInHumanWrittenCode(Field f) {
exists(File file | exists(File file |
f.getAnAccess().getFile() = file and 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 from Field field, ValueOrRefType widget, string prefix
where widget.getABaseType*().hasQualifiedName("System.Windows.Forms.Control") where
and field.getType() = widget widget.getABaseType*().hasQualifiedName("System.Windows.Forms.Control") and
and field.getName().regexpMatch(prefix + "[0-9]+") field.getType() = widget and
and controlName(prefix) field.getName().regexpMatch(prefix + "[0-9]+") and
and usedInHumanWrittenCode(field) controlName(prefix) and
usedInHumanWrittenCode(field)
select field, "Control '" + field.getName() + "' should have a meaningful name." select field, "Control '" + field.getName() + "' should have a meaningful name."

Просмотреть файл

@ -11,6 +11,7 @@
* readability * readability
* naming * naming
*/ */
import csharp import csharp
class VisibleInstanceField extends Field { class VisibleInstanceField extends Field {
@ -20,14 +21,16 @@ class VisibleInstanceField extends Field {
} }
} }
from RefType type, RefType supertype, from RefType type, RefType supertype, VisibleInstanceField masked, VisibleInstanceField masking
VisibleInstanceField masked, VisibleInstanceField masking where
where type.getABaseType+() =supertype and type.getABaseType+() = supertype and
masking.getDeclaringType() = type and masking.getDeclaringType() = type and
masked.getDeclaringType() = supertype and masked.getDeclaringType() = supertype and
masked.getName() = masking.getName() and masked.getName() = masking.getName() and
// exclude intentional masking // exclude intentional masking
not exists(FieldAccess va | va.getTarget() = masked and not exists(FieldAccess va |
va.getQualifier() instanceof BaseAccess) and va.getTarget() = masked and
type.fromSource() va.getQualifier() instanceof BaseAccess
) and
type.fromSource()
select masking, "This field shadows another field in a superclass." select masking, "This field shadows another field in a superclass."

Просмотреть файл

@ -9,10 +9,12 @@
* readability * readability
* naming * naming
*/ */
import csharp import csharp
from RefType sub, RefType sup from RefType sub, RefType sup
where sub.getABaseType() = sup and where
sub.getName() = sup.getName() and sub.getABaseType() = sup and
sub.fromSource() sub.getName() = sup.getName() and
sub.fromSource()
select sub, "Class has the same name as its base class." select sub, "Class has the same name as its base class."

Просмотреть файл

@ -10,50 +10,56 @@
import csharp import csharp
predicate sourceFile(File f) predicate sourceFile(File f) {
{
f.fromSource() and f.fromSource() and
not f.getAbsolutePath() = "null" and not f.getAbsolutePath() = "null" and
not f.getAbsolutePath().matches("%ActivXTabControl%.cs") not f.getAbsolutePath().matches("%ActivXTabControl%.cs")
} }
from Variable variable, string name from Variable variable, string name
where name = variable.getName() where
and variable.fromSource() name = variable.getName() and
and sourceFile(variable.getFile()) variable.fromSource() and
and not allowedName(name) sourceFile(variable.getFile()) and
and not allowedVariable(variable) not allowedName(name) and
// not allowedVariable(variable) and
// Adjustable parameter: //
// // Adjustable parameter:
and name.length() < 3 //
name.length() < 3
// //
select variable, "Variable name '" + name + "' is too short." select variable, "Variable name '" + name + "' is too short."
// //
// Adjustable: acceptable short names // Adjustable: acceptable short names
// //
predicate allowedName(string name) predicate allowedName(string name) {
{ name = "url" or
name = "url" or name = "cmd" or name = "UK" or name = "uri" or name = "cmd" or
name = "top" or name = "row" or name = "pin" or name = "log" or name = "UK" or
name = "key" or name = "_" 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 // Adjustable: variables that are allowed to have short names
// //
predicate allowedVariable(Variable variable) predicate allowedVariable(Variable variable) {
{ exists(Parameter param |
exists(Parameter param | variable = param and variable = param and
not exists(param.getAnAccess()) and not exists(param.getAnAccess()) and
param.getType().getName().matches("%EventArgs")) 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
) )
or
exists(LocalVariable local |
variable = local and
local.getVariableDeclExpr().getParent() instanceof CatchClause
)
or
exists(Call c, LambdaExpr le | le.getAParameter() = variable | c.getAnArgument() = le)
} }

Просмотреть файл

@ -12,6 +12,7 @@
import csharp import csharp
from Class c, Method m from Class c, Method m
where m.isExtern() where
and m.getDeclaringType() = c m.isExtern() and
m.getDeclaringType() = c
select m, "Minimise the use of unmanaged code." select m, "Minimise the use of unmanaged code."

Просмотреть файл

@ -10,6 +10,7 @@
* frameworks/asp.net * frameworks/asp.net
* external/cwe/cwe-472 * external/cwe/cwe-472
*/ */
import csharp import csharp
from ObjectCreation oc from ObjectCreation oc

Просмотреть файл

@ -7,17 +7,22 @@
* @id cs/console-output * @id cs/console-output
* @tags maintainability * @tags maintainability
*/ */
import csharp import csharp
import semmle.code.csharp.commons.Util import semmle.code.csharp.commons.Util
predicate isConsoleOutRedefinedSomewhere() { predicate isConsoleOutRedefinedSomewhere() {
exists(MethodCall mc | mc.getTarget().hasName("SetOut") and exists(MethodCall mc |
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")) mc.getTarget().hasName("SetOut") and
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")
)
} }
predicate isConsoleErrorRedefinedSomewhere() { predicate isConsoleErrorRedefinedSomewhere() {
exists(MethodCall mc | mc.getTarget().hasName("SetError") and exists(MethodCall mc |
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")) mc.getTarget().hasName("SetError") and
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")
)
} }
predicate isCallToConsoleWrite(MethodCall mc) { predicate isCallToConsoleWrite(MethodCall mc) {
@ -36,8 +41,13 @@ predicate isAccessToConsoleError(PropertyAccess pa) {
} }
from Expr e from Expr e
where (isCallToConsoleWrite(e) and not isConsoleOutRedefinedSomewhere() where
or isAccessToConsoleOut(e) and not isConsoleOutRedefinedSomewhere() (
or isAccessToConsoleError(e) and not isConsoleErrorRedefinedSomewhere()) isCallToConsoleWrite(e) and not isConsoleOutRedefinedSomewhere()
and not e.getEnclosingCallable() instanceof MainMethod 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." select e, "Poor logging: use of system output stream."

Просмотреть файл

@ -10,41 +10,38 @@
* maintainability * maintainability
* modularity * modularity
*/ */
import csharp import csharp
predicate virtualCallToSelfInConstructor(Expr e) { predicate virtualCallToSelfInConstructor(Expr e) {
exists(RefType t, Virtualizable d, Callable c | exists(RefType t, Virtualizable d, Callable c |
c = e.getEnclosingCallable() c = e.getEnclosingCallable() and
and (c instanceof Constructor or c instanceof Destructor) and
(c instanceof Constructor or c instanceof Destructor) t = c.getDeclaringType() and
and virtualAccessWithThisQualifier(e, d) and
t = c.getDeclaringType() t.getABaseType*() = d.getDeclaringType() and
and not t.isSealed() and
virtualAccessWithThisQualifier(e, d)
and
t.getABaseType*() = d.getDeclaringType()
and
not t.isSealed()
and
not overriddenSealed(t.getABaseType*(), d) not overriddenSealed(t.getABaseType*(), d)
) )
} }
predicate overriddenSealed(RefType t, Virtualizable d) { predicate overriddenSealed(RefType t, Virtualizable d) {
exists(Virtualizable od | exists(Virtualizable od |
od.getDeclaringType() = t od.getDeclaringType() = t and
and (od.getOverridee() = d or od.getImplementee() = d) and
(od.getOverridee() = d or od.getImplementee() = d)
and
not od.isOverridableOrImplementable() not od.isOverridableOrImplementable()
) )
} }
predicate virtualAccessWithThisQualifier(Expr e, Member d) { predicate virtualAccessWithThisQualifier(Expr e, Member d) {
exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier()) or exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier())
exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or or
exists(VirtualPropertyAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier())
exists(VirtualIndexerAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or 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()) exists(VirtualEventAccess c | c = e and c.getTarget() = d and c.hasThisQualifier())
} }

Просмотреть файл

@ -16,8 +16,7 @@ import semmle.code.csharp.commons.ComparisonTest
import semmle.code.csharp.commons.Constants import semmle.code.csharp.commons.Constants
predicate isBoxingTestCase(StaticEqualsCallComparisonTest ct) { predicate isBoxingTestCase(StaticEqualsCallComparisonTest ct) {
ct.isReferenceEquals() ct.isReferenceEquals() and
and
exists(TypeParameter tp | exists(TypeParameter tp |
tp = ct.getFirstArgument().stripCasts().getType() and tp = ct.getFirstArgument().stripCasts().getType() and
not tp.isValueType() 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") e.(MethodCall).getTarget().hasName("Pop")
or or
e.(MethodCall).getTarget().hasName("Push") e.(MethodCall).getTarget().hasName("Push")
@ -35,16 +33,19 @@ predicate isMutatingOperation(Expr e)
} }
from ComparisonTest ct, Expr e, string msg from ComparisonTest ct, Expr e, string msg
where comparesIdenticalValues(ct) where
and e = ct.getExpr() comparesIdenticalValues(ct) and
and not isBoxingTestCase(ct) e = ct.getExpr() and
and ( not isBoxingTestCase(ct) and
exists(string m | comparesIdenticalValuesNan(ct, m) | msg = "Comparison is equivalent to using " + m) (
exists(string m | comparesIdenticalValuesNan(ct, m) |
msg = "Comparison is equivalent to using " + m
)
or or
not comparesIdenticalValuesNan(ct, _) and msg = "Comparison of identical values." not comparesIdenticalValuesNan(ct, _) and msg = "Comparison of identical values."
) ) and
and not isMutatingOperation(ct.getAnArgument().getAChild*()) not isMutatingOperation(ct.getAnArgument().getAChild*()) and
and not isConstantCondition(e, _) // Avoid overlap with cs/constant-condition not isConstantCondition(e, _) and // Avoid overlap with cs/constant-condition
and not isConstantComparison(e, _) // Avoid overlap with cs/constant-comparison not isConstantComparison(e, _) and // Avoid overlap with cs/constant-comparison
and not isExprInAssertion(e) not isExprInAssertion(e)
select ct, msg select ct, msg

Просмотреть файл

@ -16,6 +16,7 @@ import csharp
import semmle.code.csharp.dataflow.Nullness import semmle.code.csharp.dataflow.Nullness
import PathGraph 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) where d.isFirstMaybeNull(v.getAnSsaDefinition(), source, sink, msg, reason)
select d, source, sink, "Variable $@ may be null here " + msg + ".", v, v.toString(), reason, "this" select d, source, sink, "Variable $@ may be null here " + msg + ".", v, v.toString(), reason, "this"

Просмотреть файл

@ -11,14 +11,17 @@
* testability * testability
* complexity * complexity
*/ */
import csharp import csharp
class ComplexStmt extends Stmt { class ComplexStmt extends Stmt {
ComplexStmt() { ComplexStmt() {
(this instanceof ForStmt or (
this instanceof WhileStmt or this instanceof ForStmt or
this instanceof DoStmt or this instanceof WhileStmt or
this instanceof SwitchStmt) this instanceof DoStmt or
this instanceof SwitchStmt
)
} }
} }

Просмотреть файл

@ -8,6 +8,7 @@
* @tags testability * @tags testability
* readability * readability
*/ */
import csharp import csharp
predicate nontrivialLogicalOperator(BinaryLogicalOperation e) { predicate nontrivialLogicalOperator(BinaryLogicalOperation e) {
@ -17,13 +18,13 @@ predicate nontrivialLogicalOperator(BinaryLogicalOperation e) {
) )
} }
predicate logicalParent(LogicalOperation op, LogicalOperation parent) predicate logicalParent(LogicalOperation op, LogicalOperation parent) { parent = op.getParent() }
{
parent = op.getParent()
}
from Expr e, int operators from Expr e, int operators
where not (e.getParent() instanceof LogicalOperation) where
and operators = count(BinaryLogicalOperation op | logicalParent*(op, e) and nontrivialLogicalOperator(op)) not (e.getParent() instanceof LogicalOperation) and
and operators > 3 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." select e.getLocation(), "Complex condition: too many logical operations in this expression."

Просмотреть файл

@ -21,8 +21,10 @@ predicate lockedFieldUpdate(LockStmt lock, Field f, AssignableDefinition def) {
} }
from LockStmt lock, Expr e, Field f, AssignableDefinition def from LockStmt lock, Expr e, Field f, AssignableDefinition def
where e = lock.getExpr() where
and f.getAnAccess() = e e = lock.getExpr() and
and lockedFieldUpdate(lock, f, def) f.getAnAccess() = e and
select e, "Locking field $@ guards the initial value, not the value which may be seen from another thread after $@.", 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" f, f.getName(), def, "reassignment"

Просмотреть файл

@ -38,7 +38,8 @@ LockStmt getAReachableLockStmt(Callable callable) {
predicate nestedLocks(Variable outerVariable, Variable innerVariable, LockStmt outer, LockStmt inner) { predicate nestedLocks(Variable outerVariable, Variable innerVariable, LockStmt outer, LockStmt inner) {
outerVariable = outer.getLockVariable() and outerVariable = outer.getLockVariable() and
innerVariable = inner.getLockVariable() and innerVariable = inner.getLockVariable() and
outerVariable != innerVariable and ( outerVariable != innerVariable and
(
inner = outer.getALockedStmt() inner = outer.getALockedStmt()
or or
exists(Call call | call.getEnclosingStmt() = outer.getALockedStmt() | exists(Call call | call.getEnclosingStmt() = outer.getALockedStmt() |
@ -54,9 +55,6 @@ where
nestedLocks(v1, v2, outer1, inner1) and nestedLocks(v1, v2, outer1, inner1) and
nestedLocks(v2, v1, outer2, inner2) and nestedLocks(v2, v1, outer2, inner2) and
v1.getName() <= v2.getName() v1.getName() <= v2.getName()
select v1, "Inconsistent lock sequence with $@. Lock sequences $@, $@ and $@, $@ found.", select v1, "Inconsistent lock sequence with $@. Lock sequences $@, $@ and $@, $@ found.", v2,
v2, v2.getName(), v2.getName(), outer1, v1.getName(), inner1, v2.getName(), outer2, v2.getName(), inner2,
outer1, v1.getName(), v1.getName()
inner1, v2.getName(),
outer2, v2.getName(),
inner2, v1.getName()

Просмотреть файл

@ -15,5 +15,5 @@
import csharp import csharp
from LockStmt s, ThisAccess a from LockStmt s, ThisAccess a
where a=s.getExpr() where a = s.getExpr()
select a, "'this' used in lock statement." select a, "'this' used in lock statement."

Просмотреть файл

@ -16,10 +16,19 @@ import csharp
import Concurrency import Concurrency
from LockedBlock l, WaitStmt w, string lockedItem 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(Variable v |
exists( Type t | t=l.getLockTypeObject() and not t=w.getWaitTypeObject() and lockedItem = "typeof("+t.getName()+")" ) or v = l.getLockVariable() and not v = w.getWaitVariable() and lockedItem = v.getName()
( l.isLockThis() and not w.isWaitThis() and lockedItem="this" ) )
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." select w, "'" + lockedItem + "' is locked during this wait."

Просмотреть файл

@ -15,26 +15,17 @@ import csharp
from Property p, Field f from Property p, Field f
where where
f.getDeclaringType() = p.getDeclaringType() f.getDeclaringType() = p.getDeclaringType() and
and
exists(Setter setter, LockStmt writelock, FieldWrite writeaccess | exists(Setter setter, LockStmt writelock, FieldWrite writeaccess |
p.getSetter() = setter p.getSetter() = setter and
and writeaccess = f.getAnAccess() and
writeaccess = f.getAnAccess() writelock.getEnclosingCallable() = setter and
and
writelock.getEnclosingCallable() = setter
and
writelock.getAChildStmt+().getAChildExpr+() = writeaccess writelock.getAChildStmt+().getAChildExpr+() = writeaccess
) ) and
and
exists(Getter getter, FieldRead readaccess | exists(Getter getter, FieldRead readaccess |
getter = p.getGetter() getter = p.getGetter() and
and readaccess = f.getAnAccess() and
readaccess = f.getAnAccess() readaccess.getEnclosingCallable() = getter and
and not exists(LockStmt readlock | readlock.getAChildStmt+().getAChildExpr+() = readaccess)
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() select p, "Field '$@' is guarded by a lock in the setter but not in the getter.", f, f.getName()

Просмотреть файл

@ -15,7 +15,7 @@ import csharp
import semmle.code.csharp.commons.StructuralComparison import semmle.code.csharp.commons.StructuralComparison
class DoubleCheckedLock extends StructuralComparisonConfiguration { class DoubleCheckedLock extends StructuralComparisonConfiguration {
DoubleCheckedLock() { this="double checked lock" } DoubleCheckedLock() { this = "double checked lock" }
override predicate candidate(Element x, Element y) { override predicate candidate(Element x, Element y) {
exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock | exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock |
@ -28,8 +28,7 @@ class DoubleCheckedLock extends StructuralComparisonConfiguration {
} }
predicate doubleCheckedLock(Field field, IfStmt ifs) { predicate doubleCheckedLock(Field field, IfStmt ifs) {
exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 | exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 | ifs.getCondition() = eq1 |
ifs.getCondition() = eq1 |
lock = ifs.getThen().stripSingletonBlocks() and lock = ifs.getThen().stripSingletonBlocks() and
config.same(eq1, eq2) and config.same(eq1, eq2) and
field.getAnAccess() = eq1.getAChildExpr*() field.getAnAccess() = eq1.getAChildExpr*()
@ -37,9 +36,7 @@ predicate doubleCheckedLock(Field field, IfStmt ifs) {
} }
from Field field, IfStmt ifs from Field field, IfStmt ifs
where doubleCheckedLock(field, ifs) where
and not field.isVolatile() doubleCheckedLock(field, ifs) and
select ifs, "Field $@ should be 'volatile' for this double-checked lock.", not field.isVolatile()
field, field.getName() select ifs, "Field $@ should be 'volatile' for this double-checked lock.", field, field.getName()

Просмотреть файл

@ -10,6 +10,7 @@
* external/cwe/cwe-362 * external/cwe/cwe-362
* external/cwe/cwe-567 * external/cwe/cwe-567
*/ */
import csharp import csharp
import DataMembers import DataMembers
import ThreadCreation import ThreadCreation
@ -24,7 +25,8 @@ predicate correctlySynchronized(CollectionMember c, Expr access) {
} }
ControlFlow::Node unlockedReachable(Callable a) { ControlFlow::Node unlockedReachable(Callable a) {
result = a.getEntryPoint() or result = a.getEntryPoint()
or
exists(ControlFlow::Node mid | mid = unlockedReachable(a) | exists(ControlFlow::Node mid | mid = unlockedReachable(a) |
not mid.getElement() instanceof LockingCall and not mid.getElement() instanceof LockingCall and
result = mid.getASuccessor() result = mid.getASuccessor()
@ -40,22 +42,22 @@ predicate unlockedCalls(Callable a, Callable b) {
} }
predicate writtenStaticDictionary(CollectionMember c) { predicate writtenStaticDictionary(CollectionMember c) {
c.getType().(ValueOrRefType).getABaseType*().hasName("IDictionary") c.getType().(ValueOrRefType).getABaseType*().hasName("IDictionary") and
and c.isStatic() c.isStatic() and
and exists(Expr write | write = c.getAWrite() | exists(Expr write | write = c.getAWrite() |
not write.getEnclosingCallable() instanceof StaticConstructor not write.getEnclosingCallable() instanceof StaticConstructor
) )
} }
predicate nonStaticCallable(Callable c) { predicate nonStaticCallable(Callable c) { not c.(Modifiable).isStatic() }
not c.(Modifiable).isStatic()
}
from CollectionMember c, Expr a, ConcurrentEntryPoint e,Callable enclosing from CollectionMember c, Expr a, ConcurrentEntryPoint e, Callable enclosing
where a = c.getAReadOrWrite() where
and enclosing = a.getEnclosingCallable() a = c.getAReadOrWrite() and
and nonStaticCallable(enclosing) enclosing = a.getEnclosingCallable() and
and not correctlySynchronized(c, a) nonStaticCallable(enclosing) and
and unlockedCalls*(e, enclosing) not correctlySynchronized(c, a) and
and writtenStaticDictionary(c) unlockedCalls*(e, enclosing) and
select a, "Unsynchronized access to $@ in non-static context from $@.", c, c.getName(), e, e.getName() writtenStaticDictionary(c)
select a, "Unsynchronized access to $@ in non-static context from $@.", c, c.getName(), e,
e.getName()

Просмотреть файл

@ -9,10 +9,14 @@
* external/cwe/cwe-258 * external/cwe/cwe-258
* external/cwe/cwe-862 * external/cwe/cwe-862
*/ */
import csharp import csharp
from XMLAttribute a from XMLAttribute a
where a.getName().toLowerCase() = "password" and a.getValue() = "" where
or a.getName().toLowerCase() = "pwd" and a.getValue() = "" a.getName().toLowerCase() = "password" and a.getValue() = ""
or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=\\s*;.*") or
a.getName().toLowerCase() = "pwd" and a.getValue() = ""
or
a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=\\s*;.*")
select a, "Do not use empty passwords." select a, "Do not use empty passwords."

Просмотреть файл

@ -10,10 +10,14 @@
* external/cwe/cwe-256 * external/cwe/cwe-256
* external/cwe/cwe-313 * external/cwe/cwe-313
*/ */
import csharp import csharp
from XMLAttribute a from XMLAttribute a
where a.getName().toLowerCase() = "password" and not a.getValue() = "" where
or a.getName().toLowerCase() = "pwd" and not a.getValue() = "" a.getName().toLowerCase() = "password" and not a.getValue() = ""
or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*") 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." select a, "Avoid plaintext passwords in configuration files."

Просмотреть файл

@ -9,45 +9,43 @@
* useless-code * useless-code
* external/cwe/cwe-561 * external/cwe/cwe-561
*/ */
import csharp import csharp
import semmle.code.csharp.commons.Util import semmle.code.csharp.commons.Util
import semmle.code.csharp.frameworks.Test import semmle.code.csharp.frameworks.Test
import semmle.code.csharp.metrics.Coupling import semmle.code.csharp.metrics.Coupling
predicate potentiallyUsedFromXaml(RefType t) predicate potentiallyUsedFromXaml(RefType t) {
{
exists(string name | name = t.getABaseType*().getQualifiedName() | exists(string name | name = t.getABaseType*().getQualifiedName() |
name = "System.Windows.Data.IValueConverter" name = "System.Windows.Data.IValueConverter" or
or name = "System.Windows.Data.IMultiValueConverter" name = "System.Windows.Data.IMultiValueConverter"
) )
} }
class ExportAttribute extends Attribute class ExportAttribute extends Attribute {
{ ExportAttribute() {
ExportAttribute()
{
getType().hasQualifiedName("System.ComponentModel.Composition.ExportAttribute") getType().hasQualifiedName("System.ComponentModel.Composition.ExportAttribute")
} }
} }
from RefType t from RefType t
where where
not extractionIsStandalone() not extractionIsStandalone() and
and t.fromSource() t.fromSource() and
and t = t.getSourceDeclaration() t = t.getSourceDeclaration() and
and not t instanceof AnonymousClass not t instanceof AnonymousClass and
and not (t.isPublic() or t.isProtected()) not (t.isPublic() or t.isProtected()) and
and not exists (ValueOrRefType dependent | depends(dependent, t) and dependent != t) not exists(ValueOrRefType dependent | depends(dependent, t) and dependent != t) and
and not exists (ConstructedType ct | usesType(ct, t)) not exists(ConstructedType ct | usesType(ct, t)) and
and not exists (MethodCall call | usesType(call.getTarget().(ConstructedMethod).getATypeArgument(), t)) not exists(MethodCall call | usesType(call.getTarget().(ConstructedMethod).getATypeArgument(), t)) and
and not t.getAMethod() instanceof MainMethod not t.getAMethod() instanceof MainMethod and
and not potentiallyUsedFromXaml(t) not potentiallyUsedFromXaml(t) and
and not exists(TypeofExpr typeof | typeof.getTypeAccess().getTarget() = t) not exists(TypeofExpr typeof | typeof.getTypeAccess().getTarget() = t) and
and not t instanceof TestClass not t instanceof TestClass and
// MemberConstant nodes are compile-time constant and can appear in various contexts // 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). // 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, // Classes that are declared purely to hold member constants which are used are,
// therefore, not dead. // therefore, not dead.
and not exists(t.getAMember().(MemberConstant).getAnAccess()) not exists(t.getAMember().(MemberConstant).getAnAccess()) and
and not t.getAnAttribute() instanceof ExportAttribute not t.getAnAttribute() instanceof ExportAttribute
select t, "Unused reference type " + t + "." select t, "Unused reference type " + t + "."

Просмотреть файл

@ -20,8 +20,7 @@ import csharp
Callable getACapturingCallableAncestor(LocalVariable v) { Callable getACapturingCallableAncestor(LocalVariable v) {
result = v.getACapturingCallable() result = v.getACapturingCallable()
or or
exists(Callable mid | exists(Callable mid | mid = getACapturingCallableAncestor(v) |
mid = getACapturingCallableAncestor(v) |
result = mid.getEnclosingCallable() and result = mid.getEnclosingCallable() and
not v.getEnclosingCallable() = result 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. * Holds if `c` is a call where any delegate argument is evaluated immediately.
*/ */
predicate nonEscapingCall(Call c) { predicate nonEscapingCall(Call c) {
exists(string name | exists(string name | c.getTarget().hasName(name) |
c.getTarget().hasName(name) |
name = "ForEach" or name = "ForEach" or
name = "Count" or name = "Count" or
name = "Any" or name = "Any" or
@ -62,8 +60,7 @@ predicate nonEscapingCall(Call c) {
* `v` may escape the local scope. * `v` may escape the local scope.
*/ */
predicate mayEscape(LocalVariable v) { predicate mayEscape(LocalVariable v) {
exists(Callable c, Expr e, Expr succ | exists(Callable c, Expr e, Expr succ | c = getACapturingCallableAncestor(v) |
c = getACapturingCallableAncestor(v) |
e = getADelegateExpr(c) and e = getADelegateExpr(c) and
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(succ)) and DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(succ)) and
not succ = any(DelegateCall dc).getDelegateExpr() and not succ = any(DelegateCall dc).getDelegateExpr() and
@ -80,15 +77,15 @@ class RelevantDefinition extends AssignableDefinition {
this instanceof AssignableDefinitions::MutationDefinition this instanceof AssignableDefinitions::MutationDefinition
or or
this instanceof AssignableDefinitions::TupleAssignmentDefinition this instanceof AssignableDefinitions::TupleAssignmentDefinition
or
// Discards in out assignments are only possible from C# 7 (2017), so we disable this case // Discards in out assignments are only possible from C# 7 (2017), so we disable this case
// for now // for now
//or //or
//this.(AssignableDefinitions::OutRefDefinition).getTargetAccess().isOutArgument() //this.(AssignableDefinitions::OutRefDefinition).getTargetAccess().isOutArgument()
or
this.(AssignableDefinitions::LocalVariableDefinition).getDeclaration() = any(LocalVariableDeclExpr lvde | this.(AssignableDefinitions::LocalVariableDefinition).getDeclaration() = any(LocalVariableDeclExpr lvde |
lvde = any(SpecificCatchClause scc).getVariableDeclExpr() or lvde = any(SpecificCatchClause scc).getVariableDeclExpr() or
lvde = any(ForeachStmt fs).getVariableDeclExpr() lvde = any(ForeachStmt fs).getVariableDeclExpr()
) )
or or
this instanceof AssignableDefinitions::IsPatternDefinition this instanceof AssignableDefinitions::IsPatternDefinition
or or
@ -97,8 +94,7 @@ class RelevantDefinition extends AssignableDefinition {
/** Holds if this assignment may be live. */ /** Holds if this assignment may be live. */
private predicate isMaybeLive() { private predicate isMaybeLive() {
exists(LocalVariable v | exists(LocalVariable v | v = this.getTarget() |
v = this.getTarget() |
// SSA definitions are only created for live variables // SSA definitions are only created for live variables
this = any(Ssa::ExplicitDefinition ssaDef).getADefinition() this = any(Ssa::ExplicitDefinition ssaDef).getADefinition()
or or
@ -117,10 +113,8 @@ class RelevantDefinition extends AssignableDefinition {
*/ */
private predicate isDefaultLikeInitializer() { private predicate isDefaultLikeInitializer() {
this.isInitializer() and this.isInitializer() and
exists(Expr e | exists(Expr e | e = this.getSource() |
e = this.getSource() | exists(string val | val = e.getValue() |
exists(string val |
val = e.getValue() |
val = "0" or val = "0" or
val = "-1" or val = "-1" or
val = "" or val = "" or
@ -129,7 +123,10 @@ class RelevantDefinition extends AssignableDefinition {
or or
e instanceof NullLiteral e instanceof NullLiteral
or 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 or
e instanceof DefaultValueExpr e instanceof DefaultValueExpr
or or
@ -151,8 +148,7 @@ class RelevantDefinition extends AssignableDefinition {
( (
not this.isDefaultLikeInitializer() not this.isDefaultLikeInitializer()
or or
not exists(AssignableDefinition other | not exists(AssignableDefinition other | other.getTarget() = this.getTarget() |
other.getTarget() = this.getTarget() |
other != this other != this
) )
) )
@ -161,6 +157,7 @@ class RelevantDefinition extends AssignableDefinition {
} }
from RelevantDefinition def, LocalVariable v from RelevantDefinition def, LocalVariable v
where v = def.getTarget() where
and def.isDead() v = def.getTarget() and
def.isDead()
select def, "This assignment to $@ is useless, since its value is never read.", v, v.getName() select def, "This assignment to $@ is useless, since its value is never read.", v, v.getName()

Просмотреть файл

@ -16,108 +16,102 @@ import semmle.code.csharp.frameworks.System
import semmle.code.csharp.frameworks.system.runtime.InteropServices import semmle.code.csharp.frameworks.system.runtime.InteropServices
// Any field transitively contained in t. // Any field transitively contained in t.
Field getANestedField(ValueOrRefType t) Field getANestedField(ValueOrRefType t) {
{
result.getDeclaringType() = t result.getDeclaringType() = t
or or
exists(Field mid | exists(Field mid |
mid=getANestedField(t) mid = getANestedField(t) and
and mid.getType() = result.getDeclaringType()
mid.getType() = result.getDeclaringType()) )
} }
// Any ValueOrRefType referenced by a Type, including TypeParameters. // Any ValueOrRefType referenced by a Type, including TypeParameters.
ValueOrRefType getAReferencedType(Type t) ValueOrRefType getAReferencedType(Type t) {
{
result = t result = t
or or
result = t.(TypeParameter).getASuppliedType() result = t.(TypeParameter).getASuppliedType()
} }
predicate isTypeExternallyInitialized(ValueOrRefType t) predicate isTypeExternallyInitialized(ValueOrRefType t) {
{
// The type got created via a call to PtrToStructure(). // The type got created via a call to PtrToStructure().
exists(MethodCall mc | exists(MethodCall mc |
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod() mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod() and
and
t = getAReferencedType(mc.getArgument(1).(TypeofExpr).getTypeAccess().getTarget()) t = getAReferencedType(mc.getArgument(1).(TypeofExpr).getTypeAccess().getTarget())
) )
or
// The type got created via a call to PtrToStructure(). // The type got created via a call to PtrToStructure().
or exists(MethodCall mc | exists(MethodCall mc |
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod() mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod() and
and
t = getAReferencedType(mc.getArgument(1).getType()) t = getAReferencedType(mc.getArgument(1).getType())
) )
or
// An extern method exists which could initialize the type. // An extern method exists which could initialize the type.
or exists(Method m, Parameter p | exists(Method m, Parameter p |
isExternMethod(m) and isExternMethod(m) and
p=m.getAParameter() and p = m.getAParameter() and
t = p.getType() 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. // The data structure has been cast to a pointer - all bets are off.
or exists(CastExpr c | exists(CastExpr c | t = getAReferencedType(c.getTargetType().(PointerType).getReferentType()))
t = getAReferencedType(c.getTargetType().(PointerType).getReferentType()))
} }
// The type is potentially marshaled using an extern or interop. // The type is potentially marshaled using an extern or interop.
predicate isFieldExternallyInitialized(Field f) predicate isFieldExternallyInitialized(Field f) {
{
exists(ValueOrRefType t | exists(ValueOrRefType t |
f = getANestedField(t) f = getANestedField(t) and
and isTypeExternallyInitialized(t)
isTypeExternallyInitialized(t)) )
} }
predicate isExternMethod(Method externMethod) predicate isExternMethod(Method externMethod) {
{
externMethod.isExtern() externMethod.isExtern()
or or
externMethod.getAnAttribute().getType() instanceof SystemRuntimeInteropServicesDllImportAttributeClass externMethod.getAnAttribute().getType() instanceof
SystemRuntimeInteropServicesDllImportAttributeClass
or or
externMethod.getDeclaringType().getAnAttribute().getType() instanceof SystemRuntimeInteropServicesComImportAttributeClass externMethod.getDeclaringType().getAnAttribute().getType() instanceof
SystemRuntimeInteropServicesComImportAttributeClass
} }
from Field f, FieldRead fa from Field f, FieldRead fa
where where
f.fromSource() f.fromSource() and
and not extractionIsStandalone() not extractionIsStandalone() and
and not f.isReadOnly() not f.isReadOnly() and
and not f.isConst() not f.isConst() and
and not f.getDeclaringType() instanceof Enum not f.getDeclaringType() instanceof Enum and
and not f.getType() instanceof Struct not f.getType() instanceof Struct and
and not exists(Assignment ae, Field g | not exists(Assignment ae, Field g |
ae.getLValue().(FieldAccess).getTarget() = g ae.getLValue().(FieldAccess).getTarget() = g and
and g.getSourceDeclaration() = f g.getSourceDeclaration() = f and
and not (ae.getRValue() instanceof NullLiteral) not (ae.getRValue() instanceof NullLiteral)
) ) and
and not exists(MethodCall mc, int i, Field g | not exists(MethodCall mc, int i, Field g |
exists(Parameter p | mc.getTarget().getParameter(i) = p | exists(Parameter p | mc.getTarget().getParameter(i) = p | p.isOut() or p.isRef()) and
p.isOut() or p.isRef() mc.getArgument(i) = g.getAnAccess() and
)
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 |
g.getSourceDeclaration() = f g.getSourceDeclaration() = f
and g.getInitializer() = init ) and
and not init instanceof NullLiteral not isFieldExternallyInitialized(f) and
) not exists(f.getAnAttribute()) and
and not exists(AssignOperation ua, Field g | not exists(Expr init, Field g |
ua.getLValue().(FieldAccess).getTarget() = g g.getSourceDeclaration() = f and
and g.getSourceDeclaration() = f g.getInitializer() = init and
) not init instanceof NullLiteral
and not exists(MutatorOperation op | ) 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 op.getAnOperand().(FieldAccess).getTarget().getSourceDeclaration() = f
) and
exists(Field g |
fa.getTarget() = g and
g.getSourceDeclaration() = f
) )
and exists(Field g | select f,
fa.getTarget() = g "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.", fa,
and g.getSourceDeclaration() = f "here"
)
select f, "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.",
fa, "here"

Просмотреть файл

@ -9,13 +9,14 @@
* useless-code * useless-code
* external/cwe/cwe-561 * external/cwe/cwe-561
*/ */
import csharp import csharp
import DeadCode import DeadCode
from Field f from Field f
where where
not extractionIsStandalone() not extractionIsStandalone() and
and f.fromSource() f.fromSource() and
and isDeadField(f) isDeadField(f) and
and not f.getDeclaringType().isPartial() not f.getDeclaringType().isPartial()
select f, "Unused field (or field used from dead method only)" select f, "Unused field (or field used from dead method only)"

Просмотреть файл

@ -10,13 +10,14 @@
* useless-code * useless-code
* external/cwe/cwe-561 * external/cwe/cwe-561
*/ */
import csharp import csharp
import DeadCode import DeadCode
from Method m from Method m
where where
not extractionIsStandalone() not extractionIsStandalone() and
and m.fromSource() m.fromSource() and
and isDeadMethod(m) isDeadMethod(m) and
and not m.getDeclaringType().isPartial() not m.getDeclaringType().isPartial()
select m, "Unused method (or method called from dead method only)" select m, "Unused method (or method called from dead method only)"

Просмотреть файл

@ -12,7 +12,8 @@
import Documentation import Documentation
from SourceMethodOrConstructor m, ParamXmlComment comment, string paramName from SourceMethodOrConstructor m, ParamXmlComment comment, string paramName
where comment = getADeclarationXmlComment(m) where
and comment.getName(_)=paramName comment = getADeclarationXmlComment(m) and
and not m.getAParameter().getName() = paramName comment.getName(_) = paramName and
not m.getAParameter().getName() = paramName
select m, "Documentation specifies an invalid parameter name $@.", comment, paramName select m, "Documentation specifies an invalid parameter name $@.", comment, paramName

Просмотреть файл

@ -12,7 +12,8 @@
import Documentation import Documentation
from UnboundGeneric d, TypeparamXmlComment comment, string paramName from UnboundGeneric d, TypeparamXmlComment comment, string paramName
where comment = getADeclarationXmlComment(d) where
and comment.getName(_) = paramName comment = getADeclarationXmlComment(d) and
and not d.getATypeParameter().getName() = paramName comment.getName(_) = paramName and
not d.getATypeParameter().getName() = paramName
select d, "Documentation specifies an invalid type parameter name $@.", comment, paramName select d, "Documentation specifies an invalid type parameter name $@.", comment, paramName

Просмотреть файл

@ -12,16 +12,20 @@
import Documentation import Documentation
/** Generate a user-friendly string for the declaration */ /** Generate a user-friendly string for the declaration */
string declarationDescription(Declaration d) string declarationDescription(Declaration d) {
{ d instanceof Class and result = "class"
d instanceof Class and result="class" or or
d instanceof Interface and result="interface" or d instanceof Interface and result = "interface"
d instanceof Method and result="method" or or
d instanceof Constructor and result="constructor" or d instanceof Method and result = "method"
d instanceof Struct and result="struct" or
d instanceof Constructor and result = "constructor"
or
d instanceof Struct and result = "struct"
} }
from Declaration decl from Declaration decl
where isDocumentationNeeded(decl) where
and not declarationHasXmlComment(decl) isDocumentationNeeded(decl) and
not declarationHasXmlComment(decl)
select decl, "Public " + declarationDescription(decl) + " should be documented." select decl, "Public " + declarationDescription(decl) + " should be documented."

Просмотреть файл

@ -12,15 +12,16 @@
import Documentation import Documentation
from SourceMethodOrConstructor m, ThrowElement throw, RefType throwType from SourceMethodOrConstructor m, ThrowElement throw, RefType throwType
where declarationHasXmlComment(m) where
and m = throw.getEnclosingCallable() declarationHasXmlComment(m) and
and throwType = throw.getExpr().getType() m = throw.getEnclosingCallable() and
and not exists(ExceptionXmlComment comment, int offset, string exceptionName, RefType throwBaseType | throwType = throw.getExpr().getType() and
comment = getADeclarationXmlComment(m) not exists(ExceptionXmlComment comment, int offset, string exceptionName, RefType throwBaseType |
and exceptionName = comment.getCref(offset) comment = getADeclarationXmlComment(m) and
and throwType.getABaseType*() = throwBaseType exceptionName = comment.getCref(offset) and
and (throwBaseType.hasName(exceptionName) or throwBaseType.hasQualifiedName(exceptionName)) throwType.getABaseType*() = throwBaseType and
(throwBaseType.hasName(exceptionName) or throwBaseType.hasQualifiedName(exceptionName))
// and comment.hasBody(offset) // Too slow // and comment.hasBody(offset) // Too slow
) ) and
and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
select m, "Exception $@ should be documented.", throw, throw.getExpr().getType().getName() select m, "Exception $@ should be documented.", throw, throw.getExpr().getType().getName()

Просмотреть файл

@ -12,11 +12,13 @@
import Documentation import Documentation
from SourceMethodOrConstructor m, SourceParameter p from SourceMethodOrConstructor m, SourceParameter p
where p = m.getAParameter() where
and declarationHasXmlComment(m) p = m.getAParameter() and
and not exists( ParamXmlComment c, int offset | declarationHasXmlComment(m) and
c = getADeclarationXmlComment(m) not exists(ParamXmlComment c, int offset |
and c.getName(offset) = p.getName() c = getADeclarationXmlComment(m) and
and c.hasBody(offset) ) c.getName(offset) = p.getName() and
and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment c.hasBody(offset)
) and
not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
select p, "Parameter should be documented." select p, "Parameter should be documented."

Просмотреть файл

@ -12,9 +12,11 @@
import Documentation import Documentation
from SourceMethod m from SourceMethod m
where declarationHasXmlComment(m) where
and forall(ReturnsXmlComment c | c=getADeclarationXmlComment(m) | declarationHasXmlComment(m) and
forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset) ) ) forall(ReturnsXmlComment c | c = getADeclarationXmlComment(m) |
and not m.getReturnType() instanceof VoidType forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset))
and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment ) and
not m.getReturnType() instanceof VoidType and
not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
select m, "Return value should be documented." select m, "Return value should be documented."

Просмотреть файл

@ -11,9 +11,11 @@
import Documentation import Documentation
from Declaration decl from Declaration decl
where declarationHasXmlComment(decl) where
and isDocumentationNeeded(decl) declarationHasXmlComment(decl) and
and forall(SummaryXmlComment c | c=getADeclarationXmlComment(decl) | isDocumentationNeeded(decl) and
forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset) ) ) forall(SummaryXmlComment c | c = getADeclarationXmlComment(decl) |
and not getADeclarationXmlComment(decl) instanceof InheritDocXmlComment forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset))
) and
not getADeclarationXmlComment(decl) instanceof InheritDocXmlComment
select decl, "Documentation should have a summary." select decl, "Documentation should have a summary."

Просмотреть файл

@ -12,11 +12,13 @@
import Documentation import Documentation
from UnboundGeneric d, TypeParameter p from UnboundGeneric d, TypeParameter p
where p=d.getATypeParameter() where
and declarationHasXmlComment(d) p = d.getATypeParameter() and
and not exists(TypeparamXmlComment comment, int offset | declarationHasXmlComment(d) and
comment = getADeclarationXmlComment(d) not exists(TypeparamXmlComment comment, int offset |
and comment.getName(offset) = p.getName() comment = getADeclarationXmlComment(d) and
and comment.hasBody(offset) ) comment.getName(offset) = p.getName() and
and not getADeclarationXmlComment(d) instanceof InheritDocXmlComment comment.hasBody(offset)
) and
not getADeclarationXmlComment(d) instanceof InheritDocXmlComment
select p, "Type parameter should be documented." select p, "Type parameter should be documented."

Просмотреть файл

@ -10,9 +10,11 @@
* frameworks/asp.net * frameworks/asp.net
* external/cwe/cwe-434 * external/cwe/cwe-434
*/ */
import csharp import csharp
from PropertyAccess pa from PropertyAccess pa
where pa.getTarget().hasName("PostedFile") where
and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.UI.HtmlControls", "HtmlInputFile") pa.getTarget().hasName("PostedFile") and
pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.UI.HtmlControls", "HtmlInputFile")
select pa, "Avoid using file upload." select pa, "Avoid using file upload."

Просмотреть файл

@ -9,10 +9,12 @@
* maintainability * maintainability
* frameworks/asp.net * frameworks/asp.net
*/ */
import csharp import csharp
import semmle.code.csharp.frameworks.system.web.Http import semmle.code.csharp.frameworks.system.web.Http
from IndexerAccess ia from IndexerAccess ia
where ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") where
and not isServerVariable(ia.getIndex(0)) ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") and
not isServerVariable(ia.getIndex(0))
select ia, "Ambiguous access to variable." select ia, "Ambiguous access to variable."

Просмотреть файл

@ -9,10 +9,12 @@
* maintainability * maintainability
* frameworks/asp.net * frameworks/asp.net
*/ */
import csharp import csharp
import semmle.code.csharp.frameworks.system.web.Http import semmle.code.csharp.frameworks.system.web.Http
from IndexerAccess ia from IndexerAccess ia
where ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") where
and isServerVariable(ia.getIndex(0)) ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") and
isServerVariable(ia.getIndex(0))
select ia, "Ambiguous access to server variable." select ia, "Ambiguous access to server variable."

Просмотреть файл

@ -13,10 +13,11 @@
import csharp import csharp
from ExplicitCast c, ConstructedType src, TypeParameter dest from ExplicitCast c, ConstructedType src, TypeParameter dest
where c.getExpr() instanceof ThisAccess where
and src = c.getExpr().getType() c.getExpr() instanceof ThisAccess and
and dest = c.getTargetType() src = c.getExpr().getType() and
and dest = src.getUnboundGeneric().getATypeParameter() dest = c.getTargetType() and
select c, "Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.", dest = src.getUnboundGeneric().getATypeParameter()
dest, dest.getName(), select c,
src, src.getName() "Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.",
dest, dest.getName(), src, src.getName()

Просмотреть файл

@ -19,16 +19,18 @@ class GenericCatchClause extends CatchClause {
this instanceof GeneralCatchClause this instanceof GeneralCatchClause
or or
this = any(SpecificCatchClause scc | this = any(SpecificCatchClause scc |
scc.getCaughtExceptionType() instanceof SystemExceptionClass and scc.getCaughtExceptionType() instanceof SystemExceptionClass and
not scc.hasFilterClause() not scc.hasFilterClause()
) )
} }
} }
from GenericCatchClause gcc from GenericCatchClause gcc
where forall(ThrowStmt throw | where
// ok to catch all exceptions if they may be rethrown forall(ThrowStmt throw |
gcc.getBlock().getAChildStmt+() = throw | // ok to catch all exceptions if they may be rethrown
exists(throw.getExpr()) gcc.getBlock().getAChildStmt+() = throw
) |
exists(throw.getExpr())
)
select gcc, "Generic catch clause." select gcc, "Generic catch clause."

Просмотреть файл

@ -15,25 +15,20 @@ import csharp
int isCountForIfChain(IfStmt is) { int isCountForIfChain(IfStmt is) {
exists(int rest | exists(int rest |
(if is.getElse() instanceof IfStmt then rest = isCountForIfChain(is.getElse()) else rest = 0) and
( (
if is.getElse() instanceof IfStmt then if is.getCondition().(IsTypeExpr).getCheckedType().getSourceDeclaration().fromSource()
rest = isCountForIfChain(is.getElse()) then result = 1 + rest
else else result = rest
rest = 0
)
and
(
if is.getCondition().(IsTypeExpr).getCheckedType().getSourceDeclaration().fromSource() then
result = 1 + rest
else
result = rest
) )
) )
} }
from IfStmt is, int n from IfStmt is, int n
where where
n = isCountForIfChain(is) n = isCountForIfChain(is) and
and n > 5 n > 5 and
and not exists(IfStmt other | is = other.getElse()) 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." select is,
"This if block performs a chain of " + n +
" type tests - consider alternatives, e.g. polymorphism or the visitor pattern."

Просмотреть файл

@ -13,10 +13,10 @@
import csharp import csharp
from ExplicitCast c, ValueOrRefType src, ValueOrRefType dest from ExplicitCast c, ValueOrRefType src, ValueOrRefType dest
where c.getExpr() instanceof ThisAccess where
and src = c.getExpr().getType() c.getExpr() instanceof ThisAccess and
and dest = c.getTargetType() src = c.getExpr().getType() and
and src = dest.getABaseType+() dest = c.getTargetType() and
src = dest.getABaseType+()
select c, "Downcasting 'this' from $@ to $@ introduces a dependency cycle between the two types.", select c, "Downcasting 'this' from $@ to $@ introduces a dependency cycle between the two types.",
src, src.getName(), src, src.getName(), dest, dest.getName()
dest, dest.getName()

Просмотреть файл

@ -15,11 +15,11 @@ import semmle.code.csharp.commons.Assertions
from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct
where where
ise.getExpr() instanceof ThisAccess ise.getExpr() instanceof ThisAccess and
and t = ise.getExpr().getType() t = ise.getExpr().getType() and
and ct = ise.getCheckedType() ct = ise.getCheckedType() and
and ct.getABaseType*() = t ct.getABaseType*() = t and
and not isExprInAssertion(ise) not isExprInAssertion(ise)
select ise, "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.", select ise,
ct, ct.getName(), "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.",
t, t.getName() ct, ct.getName(), t, t.getName()

Просмотреть файл

@ -17,10 +17,7 @@ import semmle.code.csharp.frameworks.system.Collections
import semmle.code.csharp.frameworks.system.collections.Generic import semmle.code.csharp.frameworks.system.collections.Generic
predicate lambdaCaptures(AnonymousFunctionExpr lambda, Variable v) { predicate lambdaCaptures(AnonymousFunctionExpr lambda, Variable v) {
exists(VariableAccess va | exists(VariableAccess va | va.getEnclosingCallable() = lambda | va.getTarget() = v)
va.getEnclosingCallable() = lambda |
va.getTarget() = v
)
} }
predicate lambdaCapturesLoopVariable(AnonymousFunctionExpr lambda, ForeachStmt loop, Variable v) { predicate lambdaCapturesLoopVariable(AnonymousFunctionExpr lambda, ForeachStmt loop, Variable v) {
@ -33,41 +30,34 @@ predicate inForeachStmtBody(ForeachStmt loop, Element e) {
e = loop.getBody() e = loop.getBody()
or or
exists(Element mid | exists(Element mid |
inForeachStmtBody(loop, mid) inForeachStmtBody(loop, mid) and
and
e = mid.getAChild() e = mid.getAChild()
) )
} }
class LambdaDataFlowConfiguration extends DataFlow::Configuration { class LambdaDataFlowConfiguration extends DataFlow::Configuration {
LambdaDataFlowConfiguration() { LambdaDataFlowConfiguration() { this = "LambdaDataFlowConfiguration" }
this = "LambdaDataFlowConfiguration"
}
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source) {
lambdaCapturesLoopVariable(source.asExpr(), _, _) lambdaCapturesLoopVariable(source.asExpr(), _, _)
} }
override predicate isSink(DataFlow::Node sink) { override predicate isSink(DataFlow::Node sink) { exists(getAssignmentTarget(sink.asExpr())) }
exists(getAssignmentTarget(sink.asExpr()))
}
predicate capturesLoopVarAndIsStoredIn(AnonymousFunctionExpr lambda, Variable loopVar, Element storage) { predicate capturesLoopVarAndIsStoredIn(
exists(DataFlow::Node sink | AnonymousFunctionExpr lambda, Variable loopVar, Element storage
this.hasFlow(DataFlow::exprNode(lambda), sink) | ) {
exists(DataFlow::Node sink | this.hasFlow(DataFlow::exprNode(lambda), sink) |
storage = getAssignmentTarget(sink.asExpr()) storage = getAssignmentTarget(sink.asExpr())
) ) and
and exists(ForeachStmt loop | lambdaCapturesLoopVariable(lambda, loop, loopVar) |
exists(ForeachStmt loop |
lambdaCapturesLoopVariable(lambda, loop, loopVar) |
not declaredInsideLoop(loop, storage) not declaredInsideLoop(loop, storage)
) )
} }
} }
Element getAssignmentTarget(Expr e) { Element getAssignmentTarget(Expr e) {
exists(Assignment a | exists(Assignment a | a.getRValue() = e |
a.getRValue() = e |
result = a.getLValue().(PropertyAccess).getTarget() or result = a.getLValue().(PropertyAccess).getTarget() or
result = a.getLValue().(FieldAccess).getTarget() or result = a.getLValue().(FieldAccess).getTarget() or
result = a.getLValue().(LocalVariableAccess).getTarget() or result = a.getLValue().(LocalVariableAccess).getTarget() or
@ -84,19 +74,16 @@ Element getAssignmentTarget(Expr e) {
Element getCollectionAssignmentTarget(Expr e) { Element getCollectionAssignmentTarget(Expr e) {
// Store into collection via method // Store into collection via method
exists(MethodCall mc, Method m, IEnumerableFlow ief, CallableFlowSourceArg source, CallableFlowSinkQualifier sink, int i | exists(
mc.getQualifier() = result.(Variable).getAnAccess() MethodCall mc, Method m, IEnumerableFlow ief, CallableFlowSourceArg source,
and CallableFlowSinkQualifier sink, int i
ief = mc.getQualifier().getType().getSourceDeclaration() |
and mc.getQualifier() = result.(Variable).getAnAccess() and
m = mc.getTarget().getSourceDeclaration() ief = mc.getQualifier().getType().getSourceDeclaration() and
and m = mc.getTarget().getSourceDeclaration() and
ief.callableFlow(source, sink, m, _) ief.callableFlow(source, sink, m, _) and
and source.getCallable() = m and
source.getCallable() = m source.getArgumentIndex() = i and
and
source.getArgumentIndex() = i
and
e = mc.getArgument(i) e = mc.getArgument(i)
) )
or or
@ -104,26 +91,29 @@ Element getCollectionAssignmentTarget(Expr e) {
e = result.(ArrayCreation).getInitializer().getAnElement() e = result.(ArrayCreation).getInitializer().getAnElement()
or or
// Collection initializer // Collection initializer
e = result.(ObjectCreation).getInitializer().(CollectionInitializer).getElementInitializer(_).getAnArgument() e = result
.(ObjectCreation)
.getInitializer()
.(CollectionInitializer)
.getElementInitializer(_)
.getAnArgument()
or or
// Store values using indexer // Store values using indexer
exists(IndexerAccess ia, AssignExpr ae | exists(IndexerAccess ia, AssignExpr ae |
ia.getQualifier() = result.(Variable).getAnAccess() ia.getQualifier() = result.(Variable).getAnAccess() and
and ia = ae.getLValue() and
ia = ae.getLValue()
and
e = ae.getRValue() e = ae.getRValue()
) )
} }
// Variable v is declared inside the loop body // Variable v is declared inside the loop body
predicate declaredInsideLoop(ForeachStmt loop, LocalVariable v) { predicate declaredInsideLoop(ForeachStmt loop, LocalVariable v) {
exists(LocalVariableDeclStmt decl | exists(LocalVariableDeclStmt decl | decl.getVariableDeclExpr(_).getVariable() = v |
decl.getVariableDeclExpr(_).getVariable() = v |
inForeachStmtBody(loop, decl) inForeachStmtBody(loop, decl)
) )
} }
from LambdaDataFlowConfiguration c, AnonymousFunctionExpr lambda, Variable loopVar, Element storage from LambdaDataFlowConfiguration c, AnonymousFunctionExpr lambda, Variable loopVar, Element storage
where c.capturesLoopVarAndIsStoredIn(lambda, loopVar, 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()

Просмотреть файл

@ -13,8 +13,7 @@
import csharp import csharp
predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) { predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) {
def.getTarget().getSourceDeclaration() = f def.getTarget().getSourceDeclaration() = f and
and
( (
def.getEnclosingCallable().(Constructor).getDeclaringType() = f.getDeclaringType() def.getEnclosingCallable().(Constructor).getDeclaringType() = f.getDeclaringType()
or or
@ -23,15 +22,15 @@ predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) {
} }
predicate canBeReadonly(Field f) { predicate canBeReadonly(Field f) {
forex(AssignableDefinition def | forex(AssignableDefinition def | def.getTarget().getSourceDeclaration() = f |
def.getTarget().getSourceDeclaration() = f |
isReadonlyCompatibleDefinition(def, f) isReadonlyCompatibleDefinition(def, f)
) )
} }
from Field f from Field f
where canBeReadonly(f) where
and not f.isConst() canBeReadonly(f) and
and not f.isReadOnly() not f.isConst() and
and (f.isEffectivelyPrivate() or f.isEffectivelyInternal()) not f.isReadOnly() and
(f.isEffectivelyPrivate() or f.isEffectivelyInternal())
select f, "Field '" + f.getName() + "' can be 'readonly'." select f, "Field '" + f.getName() + "' can be 'readonly'."

Просмотреть файл

@ -13,25 +13,21 @@ import csharp
import semmle.code.csharp.commons.StructuralComparison import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration { class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { StructuralComparisonConfig() { this = "MissedTernaryOpportunity" }
this = "MissedTernaryOpportunity"
}
override predicate candidate(Element x, Element y) { override predicate candidate(Element x, Element y) {
exists(IfStmt is, AssignExpr ae1 | exists(IfStmt is, AssignExpr ae1 |
ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr() | ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr()
x = ae1.getLValue() |
and x = ae1.getLValue() and
exists(AssignExpr ae2 | exists(AssignExpr ae2 | ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() |
ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() |
y = ae2.getLValue() y = ae2.getLValue()
) )
) )
} }
IfStmt getIfStmt() { IfStmt getIfStmt() {
exists(AssignExpr ae | exists(AssignExpr ae | ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() |
ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() |
same(ae.getLValue(), _) same(ae.getLValue(), _)
) )
} }
@ -41,14 +37,16 @@ from IfStmt is, string what
where where
( (
( (
is.getThen().stripSingletonBlocks() instanceof ReturnStmt is.getThen().stripSingletonBlocks() instanceof ReturnStmt and
and is.getElse().stripSingletonBlocks() instanceof ReturnStmt is.getElse().stripSingletonBlocks() instanceof ReturnStmt and
and what = "return" what = "return"
) )
or exists(StructuralComparisonConfig c | or
is = c.getIfStmt() exists(StructuralComparisonConfig c |
and what = "write to the same variable" is = c.getIfStmt() and
what = "write to the same variable"
) )
) ) and
and not exists(IfStmt other | is = other.getElse()) not exists(IfStmt other | is = other.getElse())
select is, "Both branches of this 'if' statement " + what + " - consider using '?' to express intent better." select is,
"Both branches of this 'if' statement " + what + " - consider using '?' to express intent better."

Просмотреть файл

@ -13,27 +13,22 @@ import csharp
import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.System
/** A call to IDisposable.Dispose or a method that overrides it. */ /** A call to IDisposable.Dispose or a method that overrides it. */
class DisposeCall extends MethodCall class DisposeCall extends MethodCall {
{ DisposeCall() { getTarget() instanceof DisposeMethod }
DisposeCall()
{
getTarget() instanceof DisposeMethod
}
/** The object being disposed by the call (provided it can be easily determined). */ /** The object being disposed by the call (provided it can be easily determined). */
Variable getDisposee() Variable getDisposee() {
{
exists(VariableAccess va | exists(VariableAccess va |
va = getQualifier().stripCasts() va = getQualifier().stripCasts() and
and result = va.getTarget() result = va.getTarget()
) )
} }
} }
from Variable v, DisposeCall c, TryStmt ts from Variable v, DisposeCall c, TryStmt ts
where where
v = c.getDisposee() v = c.getDisposee() and
and c = ts.getFinally().getAChild*() c = ts.getFinally().getAChild*()
select v, "This variable is manually $@ in a $@ - consider a C# using statement as a preferable resource management technique.", select v,
c, "disposed", "This variable is manually $@ in a $@ - consider a C# using statement as a preferable resource management technique.",
ts.getFinally(), "finally block" c, "disposed", ts.getFinally(), "finally block"

Просмотреть файл

@ -13,9 +13,7 @@ import csharp
from IfStmt outer, IfStmt inner from IfStmt outer, IfStmt inner
where where
inner = outer.getThen().stripSingletonBlocks() inner = outer.getThen().stripSingletonBlocks() and
and not exists(outer.getElse()) and
not exists(outer.getElse())
and
not exists(inner.getElse()) not exists(inner.getElse())
select outer, "These 'if' statements can be combined." select outer, "These 'if' statements can be combined."

Просмотреть файл

@ -13,19 +13,18 @@
import csharp import csharp
CatchClause containingCatchClause(Stmt s) CatchClause containingCatchClause(Stmt s) {
{
result.getBlock() = s result.getBlock() = s
or or
exists(Stmt mid | exists(Stmt mid |
result = containingCatchClause(mid) result = containingCatchClause(mid) and
and mid.getAChildStmt() = s and
mid.getAChildStmt() = s not mid instanceof CatchClause
and )
not mid instanceof CatchClause)
} }
from SpecificCatchClause cc, ThrowStmt throw from SpecificCatchClause cc, ThrowStmt throw
where throw.getExpr() = cc.getVariable().getAnAccess() where
and containingCatchClause(throw) = cc throw.getExpr() = cc.getVariable().getAnAccess() and
containingCatchClause(throw) = cc
select throw, "Rethrowing exception variable." select throw, "Rethrowing exception variable."

Просмотреть файл

@ -16,8 +16,7 @@ import csharp
* No other child nodes are boolean literals. * No other child nodes are boolean literals.
*/ */
predicate literalChild(Expr expr, int child, boolean value) { predicate literalChild(Expr expr, int child, boolean value) {
value = expr.getChild(child).(BoolLiteral).getBoolValue() value = expr.getChild(child).(BoolLiteral).getBoolValue() and
and
forall(int c | c != child | not expr.getChild(c) instanceof BoolLiteral) 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. * No other child nodes are boolean literals.
*/ */
predicate literalChildren(Expr expr, int child1, boolean value1, int child2, boolean value2) { predicate literalChildren(Expr expr, int child1, boolean value1, int child2, boolean value2) {
value1 = expr.getChild(child1).(BoolLiteral).getBoolValue() value1 = expr.getChild(child1).(BoolLiteral).getBoolValue() and
and value2 = expr.getChild(child2).(BoolLiteral).getBoolValue() and
value2 = expr.getChild(child2).(BoolLiteral).getBoolValue()
and
forall(int c | c != child1 and c != child2 | not expr.getChild(c) instanceof BoolLiteral) 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] 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 rewriteBinaryExpr(op, false, oldPattern) and newPattern = withFalseOperand
or or
rewriteBinaryExpr(op, true, oldPattern) and newPattern = withTrueOperand rewriteBinaryExpr(op, true, oldPattern) and newPattern = withTrueOperand
@ -55,7 +55,9 @@ predicate rewriteConditionalExpr(ConditionalExpr cond, string oldPattern, string
or or
literalChild(cond, 2, true) and oldPattern = "A ? B : true" and newPattern = "!A || B" literalChild(cond, 2, true) and oldPattern = "A ? B : true" and newPattern = "!A || B"
or 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 or
literalChildren(cond, 1, true, 2, false) and oldPattern = "A ? true : false" and newPattern = "A" literalChildren(cond, 1, true, 2, false) and oldPattern = "A ? true : false" and newPattern = "A"
or or
@ -86,19 +88,18 @@ predicate pushNegation(LogicalNotExpr expr, string oldPattern, string newPattern
expr.getOperand() instanceof LogicalNotExpr and oldPattern = "!!A" and newPattern = "A" expr.getOperand() instanceof LogicalNotExpr and oldPattern = "!!A" and newPattern = "A"
or or
exists(string oldOperator, string newOperator | exists(string oldOperator, string newOperator |
oldOperator = expr.getOperand().(BinaryOperation).getOperator() oldOperator = expr.getOperand().(BinaryOperation).getOperator() and
and
negatedOperators(oldOperator, newOperator) negatedOperators(oldOperator, newOperator)
| |
oldPattern = "!(A " + oldOperator + " B)" oldPattern = "!(A " + oldOperator + " B)" and
and
newPattern = "A " + newOperator + " B" newPattern = "A " + newOperator + " B"
) )
} }
predicate rewrite(Expr expr, string oldPattern, string newPattern) { predicate rewrite(Expr expr, string oldPattern, string newPattern) {
exists(string withFalseOperand, string withTrueOperand | exists(string withFalseOperand, string withTrueOperand |
simplifyBinaryExpr(expr.(BinaryOperation).getOperator(), withFalseOperand, withTrueOperand) | simplifyBinaryExpr(expr.(BinaryOperation).getOperator(), withFalseOperand, withTrueOperand)
|
rewriteBinaryExpr(expr, oldPattern, withFalseOperand, withTrueOperand, newPattern) rewriteBinaryExpr(expr, oldPattern, withFalseOperand, withTrueOperand, newPattern)
) )
or or
@ -108,8 +109,9 @@ predicate rewrite(Expr expr, string oldPattern, string newPattern) {
} }
from Expr expr, string oldPattern, string newPattern, string action from Expr expr, string oldPattern, string newPattern, string action
where rewrite(expr, oldPattern, newPattern) where
and if newPattern = "true" or newPattern = "false" rewrite(expr, oldPattern, newPattern) and
if newPattern = "true" or newPattern = "false"
then action = "is always" then action = "is always"
else action = "can be simplified to" else action = "can be simplified to"
select expr, "The expression '" + oldPattern + "' " + action + " '" + newPattern + "'." select expr, "The expression '" + oldPattern + "' " + action + " '" + newPattern + "'."

Просмотреть файл

@ -14,10 +14,11 @@
import csharp import csharp
from Setter setter from Setter setter
where not exists(setter.getAParameter().getAnAccess()) where
and not exists(ThrowStmt t | t.getEnclosingCallable()=setter) not exists(setter.getAParameter().getAnAccess()) and
and setter.hasBody() // Trivial setter is OK not exists(ThrowStmt t | t.getEnclosingCallable() = setter) and
and not setter.getDeclaration().overrides() setter.hasBody() and // Trivial setter is OK
and not setter.getDeclaration().implements() not setter.getDeclaration().overrides() and
and not setter.getDeclaration().isVirtual() not setter.getDeclaration().implements() and
not setter.getDeclaration().isVirtual()
select setter, "Value ignored when setting property." select setter, "Value ignored when setting property."

Просмотреть файл

@ -13,9 +13,10 @@
import csharp import csharp
from ExplicitCast cast, Expr e, Type type from ExplicitCast cast, Expr e, Type type
where e = cast.getExpr() where
and type = cast.getTargetType() e = cast.getExpr() and
and type = e.getType() type = cast.getTargetType() and
and not type instanceof NullType type = e.getType() and
and not e.(ImplicitDelegateCreation).getArgument() instanceof AnonymousFunctionExpr not type instanceof NullType and
not e.(ImplicitDelegateCreation).getArgument() instanceof AnonymousFunctionExpr
select cast, "This cast is redundant because the expression already has type " + type + "." select cast, "This cast is redundant because the expression already has type " + type + "."

Просмотреть файл

@ -14,20 +14,15 @@ import csharp
import semmle.code.csharp.commons.StructuralComparison import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration { class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { StructuralComparisonConfig() { this = "UselessIsBeforeAs" }
this = "UselessIsBeforeAs"
}
override predicate candidate(Element x, Element y) { override predicate candidate(Element x, Element y) {
exists(IfStmt is, AsExpr ae, IsTypeExpr ie | exists(IfStmt is, AsExpr ae, IsTypeExpr ie |
ie = is.getCondition().getAChild*() ie = is.getCondition().getAChild*() and
and ae.getTargetType() = ie.getCheckedType() and
ae.getTargetType() = ie.getCheckedType() x = ie.getExpr() and
and
x = ie.getExpr()
and
y = ae.getExpr() y = ae.getExpr()
| |
ae = is.getThen().getAChild*() ae = is.getThen().getAChild*()
or or
ae = is.getElse().getAChild*() ae = is.getElse().getAChild*()
@ -36,10 +31,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration {
predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) { predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) {
exists(Expr x, Expr y | exists(Expr x, Expr y |
same(x, y) same(x, y) and
and ie.getExpr() = x and
ie.getExpr() = x
and
ae.getExpr() = y ae.getExpr() = y
) )
} }
@ -47,8 +40,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration {
from AsExpr ae, IsExpr ie from AsExpr ae, IsExpr ie
where where
exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) and
and
not exists(MethodCall mc | ae = mc.getAnArgument().getAChildExpr*()) 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" ie, "here"

Просмотреть файл

@ -15,23 +15,19 @@ import csharp
import semmle.code.csharp.commons.StructuralComparison import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration { class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { StructuralComparisonConfig() { this = "UselessNullCoalescingExpression" }
this = "UselessNullCoalescingExpression"
}
override predicate candidate(Element x, Element y) { override predicate candidate(Element x, Element y) {
exists(NullCoalescingExpr nce | exists(NullCoalescingExpr nce |
x.(Access) = nce.getLeftOperand() x.(Access) = nce.getLeftOperand() and
and
y.(Access) = nce.getRightOperand().getAChildExpr*() y.(Access) = nce.getRightOperand().getAChildExpr*()
) )
} }
NullCoalescingExpr getUselessNullCoalescingExpr() { NullCoalescingExpr getUselessNullCoalescingExpr() {
exists(AssignableAccess x | exists(AssignableAccess x |
result.getLeftOperand() = x result.getLeftOperand() = x and
and forex(AssignableAccess y | same(x, y) | y instanceof AssignableRead and not y.isRefArgument())
forex(AssignableAccess y | same(x,y) | y instanceof AssignableRead and not y.isRefArgument())
) )
} }
} }

Просмотреть файл

@ -14,9 +14,9 @@ import csharp
from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct
where where
t = ise.getExpr().getType() t = ise.getExpr().getType() and
and ct = ise.getCheckedType() ct = ise.getCheckedType() and
and ct = t.getABaseType+() ct = t.getABaseType+()
select ise, "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", select ise,
t, t.getName(), "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t,
ct, ct.getName() t.getName(), ct, ct.getName()

Просмотреть файл

@ -13,17 +13,11 @@
import csharp import csharp
/** A static callable. */ /** A static callable. */
class StaticCallable extends Callable { class StaticCallable extends Callable { StaticCallable() { this.(Modifiable).isStatic() } }
StaticCallable() {
this.(Modifiable).isStatic()
}
}
/** An instance callable, that is, a non-static callable. */ /** An instance callable, that is, a non-static callable. */
class InstanceCallable extends Callable { class InstanceCallable extends Callable {
InstanceCallable() { InstanceCallable() { not this instanceof StaticCallable }
not this instanceof StaticCallable
}
} }
/** A call to a static callable. */ /** 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`. */ /** Holds `t` has instance callable `c` as a member, with name `name`. */
pragma [noinline] pragma[noinline]
predicate hasInstanceCallable(ValueOrRefType t, InstanceCallable c, string name) { predicate hasInstanceCallable(ValueOrRefType t, InstanceCallable c, string name) {
t.hasMember(c) and t.hasMember(c) and
name = c.getName() name = c.getName()
} }
/** Holds if extension method `m` is a method on `t` with name `name`. */ /** 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) { predicate hasExtensionMethod(ValueOrRefType t, ExtensionMethod m, string name) {
t.isImplicitlyConvertibleTo(m.getExtendedType()) and t.isImplicitlyConvertibleTo(m.getExtendedType()) and
name = m.getName() name = m.getName()
} }
/** Holds `t` has static callable `c` as a member, with name `name`. */ /** Holds `t` has static callable `c` as a member, with name `name`. */
pragma [noinline] pragma[noinline]
predicate hasStaticCallable(ValueOrRefType t, StaticCallable c, string name) { predicate hasStaticCallable(ValueOrRefType t, StaticCallable c, string name) {
t.hasMember(c) and t.hasMember(c) and
name = c.getName() 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`. */ /** Gets the minimum number of arguments required to call `c`. */
int getMinimumArguments(Callable c) { int getMinimumArguments(Callable c) {
result = count(Parameter p | result = count(Parameter p |
p = c.getAParameter() and p = c.getAParameter() and
not p.hasDefaultValue() not p.hasDefaultValue()
) )
} }
/** Gets the maximum number of arguments allowed to call `c`, if any. */ /** Gets the maximum number of arguments allowed to call `c`, if any. */
@ -72,6 +66,7 @@ int getMaximumArguments(Callable c) {
/** An explicit upcast. */ /** An explicit upcast. */
class ExplicitUpcast extends ExplicitCast { class ExplicitUpcast extends ExplicitCast {
ValueOrRefType src; ValueOrRefType src;
ValueOrRefType dest; ValueOrRefType dest;
ExplicitUpcast() { ExplicitUpcast() {
@ -93,10 +88,9 @@ class ExplicitUpcast extends ExplicitCast {
} }
/** Holds if this upcast may be used to disambiguate the target of an instance call. */ /** 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) { private predicate isDisambiguatingInstanceCall(InstanceCallable other, int args) {
exists(Call c, InstanceCallable target, ValueOrRefType t | exists(Call c, InstanceCallable target, ValueOrRefType t | this.isArgument(c, target) |
this.isArgument(c, target) |
t = c.(QualifiableExpr).getQualifier().getType() and t = c.(QualifiableExpr).getQualifier().getType() and
hasInstanceCallable(t, other, target.getName()) and hasInstanceCallable(t, other, target.getName()) and
args = c.getNumberOfArguments() 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. */ /** 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) { private predicate isDisambiguatingExtensionCall(ExtensionMethod other, int args) {
exists(ExtensionMethodCall c, ExtensionMethod target, ValueOrRefType t | exists(ExtensionMethodCall c, ExtensionMethod target, ValueOrRefType t |
this.isArgument(c, target) | this.isArgument(c, target)
|
not c.isOrdinaryStaticCall() and not c.isOrdinaryStaticCall() and
t = target.getParameter(0).getType() and t = target.getParameter(0).getType() and
hasExtensionMethod(t, other, target.getName()) and hasExtensionMethod(t, other, target.getName()) and
@ -117,8 +112,10 @@ class ExplicitUpcast extends ExplicitCast {
) )
} }
pragma [nomagic] pragma[nomagic]
private predicate isDisambiguatingStaticCall0(StaticCall c, StaticCallable target, string name, ValueOrRefType t) { private predicate isDisambiguatingStaticCall0(
StaticCall c, StaticCallable target, string name, ValueOrRefType t
) {
this.isArgument(c, target) and this.isArgument(c, target) and
name = target.getName() 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. */ /** 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) { private predicate isDisambiguatingStaticCall(StaticCallable other, int args) {
exists(StaticCall c, StaticCallable target, ValueOrRefType t, string name | 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 hasStaticCallable(t, other, name) and
args = c.getNumberOfArguments() and args = c.getNumberOfArguments() and
other != target other != target
@ -148,7 +146,7 @@ class ExplicitUpcast extends ExplicitCast {
this.isDisambiguatingExtensionCall(other, args) this.isDisambiguatingExtensionCall(other, args)
or or
this.isDisambiguatingStaticCall(other, args) this.isDisambiguatingStaticCall(other, args)
| |
args >= getMinimumArguments(other) and args >= getMinimumArguments(other) and
not args > getMaximumArguments(other) not args > getMaximumArguments(other)
) )
@ -164,29 +162,27 @@ class ExplicitUpcast extends ExplicitCast {
this = any(OperatorCall oc).getAnArgument() this = any(OperatorCall oc).getAnArgument()
or or
this = any(Operation o | this = any(Operation o |
not o instanceof Assignment and not o instanceof Assignment and
not o instanceof UnaryBitwiseOperation and not o instanceof UnaryBitwiseOperation and
not o instanceof SizeofExpr and not o instanceof SizeofExpr and
not o instanceof PointerIndirectionExpr and not o instanceof PointerIndirectionExpr and
not o instanceof AddressOfExpr and not o instanceof AddressOfExpr and
not o instanceof UnaryLogicalOperation and not o instanceof UnaryLogicalOperation and
not o instanceof BinaryBitwiseOperation and not o instanceof BinaryBitwiseOperation and
not o instanceof LogicalAndExpr and not o instanceof LogicalAndExpr and
not o instanceof LogicalOrExpr not o instanceof LogicalOrExpr
).getAnOperand() ).getAnOperand()
or or
this = any(LocalVariableDeclAndInitExpr decl | this = any(LocalVariableDeclAndInitExpr decl | decl.isImplicitlyTyped()).getInitializer()
decl.isImplicitlyTyped()
).getInitializer()
or or
exists(LambdaExpr c | c.canReturn(this)) exists(LambdaExpr c | c.canReturn(this))
} }
} }
from ExplicitUpcast u, ValueOrRefType src, ValueOrRefType dest from ExplicitUpcast u, ValueOrRefType src, ValueOrRefType dest
where src = u.getSourceType() where
and dest = u.getTargetType() src = u.getSourceType() and
and not u.isUseful() dest = u.getTargetType() and
select u, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", not u.isUseful()
src, src.getName(), select u, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", src,
dest, dest.getName() src.getName(), dest, dest.getName()

Просмотреть файл

@ -9,6 +9,7 @@
* @tags reliability * @tags reliability
* correctness * correctness
*/ */
import csharp import csharp
predicate isDefinitelyPositive(Expr e) { predicate isDefinitelyPositive(Expr e) {
@ -18,11 +19,16 @@ predicate isDefinitelyPositive(Expr e) {
} }
from BinaryOperation t, RemExpr lhs, IntegerLiteral rhs, string parity from BinaryOperation t, RemExpr lhs, IntegerLiteral rhs, string parity
where t.getLeftOperand() = lhs and where
t.getRightOperand() = rhs and t.getLeftOperand() = lhs and
not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and t.getRightOperand() = rhs and
lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and
((t instanceof EQExpr and rhs.getValue() = "1" and parity = "oddness") or lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and
(t instanceof NEExpr and rhs.getValue() = "1" and parity = "evenness") or (
(t instanceof GTExpr and rhs.getValue() = "0" and parity = "oddness")) (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." select t, "Possibly invalid test for " + parity + ". This will fail for negative numbers."

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше