зеркало из https://github.com/github/codeql.git
C#: Autoformat QL queries
This commit is contained in:
Родитель
4348de3120
Коммит
daa45322b1
|
@ -8,12 +8,13 @@
|
|||
* @tags efficiency
|
||||
* maintainability
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from MethodCall c, Method gcCollect
|
||||
where
|
||||
c.getTarget() = gcCollect
|
||||
and gcCollect.hasName("Collect")
|
||||
and gcCollect.hasNoParameters()
|
||||
and gcCollect.getDeclaringType().hasQualifiedName("System.GC")
|
||||
c.getTarget() = gcCollect and
|
||||
gcCollect.hasName("Collect") and
|
||||
gcCollect.hasNoParameters() and
|
||||
gcCollect.getDeclaringType().hasQualifiedName("System.GC")
|
||||
select c, "Call to 'GC.Collect()'."
|
||||
|
|
|
@ -14,13 +14,12 @@
|
|||
import csharp
|
||||
|
||||
class ObsoleteAttribute extends Attribute {
|
||||
ObsoleteAttribute() {
|
||||
this.getType().hasQualifiedName("System", "ObsoleteAttribute")
|
||||
}
|
||||
ObsoleteAttribute() { this.getType().hasQualifiedName("System", "ObsoleteAttribute") }
|
||||
}
|
||||
|
||||
from MethodCall c, Method m
|
||||
where m = c.getTarget()
|
||||
and m.getAnAttribute() instanceof ObsoleteAttribute
|
||||
and not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute
|
||||
where
|
||||
m = c.getTarget() and
|
||||
m.getAnAttribute() instanceof ObsoleteAttribute and
|
||||
not c.getEnclosingCallable().(Attributable).getAnAttribute() instanceof ObsoleteAttribute
|
||||
select c, "Call to obsolete method $@.", m, m.getName()
|
||||
|
|
|
@ -16,28 +16,30 @@ import semmle.code.csharp.frameworks.System
|
|||
|
||||
from Class c, Element item, string message, string itemText
|
||||
where
|
||||
c.isSourceDeclaration()
|
||||
and not implementsEquals(c)
|
||||
and not c.isAbstract()
|
||||
and
|
||||
c.isSourceDeclaration() and
|
||||
not implementsEquals(c) and
|
||||
not c.isAbstract() and
|
||||
(
|
||||
exists(MethodCall callToEquals |
|
||||
callToEquals.getTarget() instanceof EqualsMethod
|
||||
and callToEquals.getQualifier().getType() = c
|
||||
and message = "but it is called $@"
|
||||
and item = callToEquals
|
||||
and itemText = "here" )
|
||||
callToEquals.getTarget() instanceof EqualsMethod and
|
||||
callToEquals.getQualifier().getType() = c and
|
||||
message = "but it is called $@" and
|
||||
item = callToEquals and
|
||||
itemText = "here"
|
||||
)
|
||||
or
|
||||
( item = c.getAnOperator().(EQOperator)
|
||||
and message = "but it implements $@"
|
||||
and itemText = "operator ==" )
|
||||
(
|
||||
item = c.getAnOperator().(EQOperator) and
|
||||
message = "but it implements $@" and
|
||||
itemText = "operator =="
|
||||
)
|
||||
or
|
||||
exists(IEquatableEqualsMethod eq | item = eq
|
||||
and eq = c.getAMethod()
|
||||
and message = "but it implements $@"
|
||||
and itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals"
|
||||
exists(IEquatableEqualsMethod eq |
|
||||
item = eq and
|
||||
eq = c.getAMethod() and
|
||||
message = "but it implements $@" and
|
||||
itemText = "IEquatable<" + eq.getParameter(0).getType() + ">.Equals"
|
||||
)
|
||||
)
|
||||
|
||||
select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".",
|
||||
item, itemText
|
||||
select c, "Class '" + c.getName() + "' does not implement Equals(object), " + message + ".", item,
|
||||
itemText
|
||||
|
|
|
@ -14,8 +14,8 @@ import csharp
|
|||
|
||||
from ValueOrRefType c
|
||||
where
|
||||
c.fromSource()
|
||||
and c.getABaseInterface+().hasQualifiedName("System", "ICloneable")
|
||||
and not c.isSealed()
|
||||
and exists(Method m | m.getDeclaringType() = c and m.hasName("Clone"))
|
||||
c.fromSource() and
|
||||
c.getABaseInterface+().hasQualifiedName("System", "ICloneable") and
|
||||
not c.isSealed() and
|
||||
exists(Method m | m.getDeclaringType() = c and m.hasName("Clone"))
|
||||
select c, "Class '" + c.getName() + "' implements 'ICloneable'."
|
||||
|
|
|
@ -29,7 +29,8 @@ ExceptionClass getAThrownException(Method m) {
|
|||
or
|
||||
exists(ControlFlowElement cfe |
|
||||
cfe = any(ThrowElement te | result = te.getExpr().getType()) or
|
||||
cfe = any(MethodCall mc | result = getAThrownException(mc.getARuntimeTarget())) |
|
||||
cfe = any(MethodCall mc | result = getAThrownException(mc.getARuntimeTarget()))
|
||||
|
|
||||
cfe.getEnclosingCallable() = m and
|
||||
not isTriedAgainstException(cfe, result)
|
||||
)
|
||||
|
@ -39,7 +40,7 @@ ExceptionClass getAThrownException(Method m) {
|
|||
* Holds if control flow element is tried against throwing an exception of type
|
||||
* `ec`.
|
||||
*/
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) {
|
||||
(cfe instanceof ThrowElement or cfe instanceof MethodCall) and
|
||||
exists(TryStmt ts |
|
||||
|
@ -53,22 +54,27 @@ predicate isTriedAgainstException(ControlFlowElement cfe, ExceptionClass ec) {
|
|||
*/
|
||||
predicate disposeReachableFromDisposableCreation(MethodCall disposeCall, Expr disposableCreation) {
|
||||
// The qualifier of the Dispose call flows from something that introduced a disposable into scope
|
||||
(disposableCreation instanceof LocalScopeDisposableCreation or disposableCreation instanceof MethodCall)
|
||||
and DataFlow::localFlowStep+(DataFlow::exprNode(disposableCreation), DataFlow::exprNode(disposeCall.getQualifier()))
|
||||
and disposeCall.getTarget() instanceof DisposeMethod
|
||||
(
|
||||
disposableCreation instanceof LocalScopeDisposableCreation or
|
||||
disposableCreation instanceof MethodCall
|
||||
) and
|
||||
DataFlow::localFlowStep+(DataFlow::exprNode(disposableCreation),
|
||||
DataFlow::exprNode(disposeCall.getQualifier())) and
|
||||
disposeCall.getTarget() instanceof DisposeMethod
|
||||
}
|
||||
|
||||
|
||||
from MethodCall disposeCall, Expr disposableCreation, MethodCall callThatThrows
|
||||
where
|
||||
disposeReachableFromDisposableCreation(disposeCall, disposableCreation)
|
||||
disposeReachableFromDisposableCreation(disposeCall, disposableCreation) and
|
||||
// The dispose call is not, itself, within a dispose method.
|
||||
and not disposeCall.getEnclosingCallable() instanceof DisposeMethod
|
||||
not disposeCall.getEnclosingCallable() instanceof DisposeMethod and
|
||||
// Dispose call not within a finally or catch block
|
||||
and not exists(TryStmt ts |
|
||||
ts.getACatchClause().getAChild*() = disposeCall or ts.getFinally().getAChild*() = disposeCall)
|
||||
not exists(TryStmt ts |
|
||||
ts.getACatchClause().getAChild*() = disposeCall or ts.getFinally().getAChild*() = disposeCall
|
||||
) and
|
||||
// At least one method call exists between the allocation and disposal that could throw
|
||||
and disposableCreation.getAReachableElement() = callThatThrows
|
||||
and callThatThrows.getAReachableElement() = disposeCall
|
||||
and exists(getAThrownException(callThatThrows.getARuntimeTarget()))
|
||||
select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows, callThatThrows.toString()
|
||||
disposableCreation.getAReachableElement() = callThatThrows and
|
||||
callThatThrows.getAReachableElement() = disposeCall and
|
||||
exists(getAThrownException(callThatThrows.getARuntimeTarget()))
|
||||
select disposeCall, "Dispose missed if exception is thrown by $@.", callThatThrows,
|
||||
callThatThrows.toString()
|
||||
|
|
|
@ -13,8 +13,9 @@ import csharp
|
|||
import semmle.code.csharp.frameworks.Format
|
||||
|
||||
from FormatCall format, ValidFormatString src, int used, int supplied
|
||||
where src = format.getAFormatSource()
|
||||
and used = src.getAnInsert()
|
||||
and supplied = format.getSuppliedArguments()
|
||||
and used >= supplied
|
||||
where
|
||||
src = format.getAFormatSource() and
|
||||
used = src.getAnInsert() and
|
||||
supplied = format.getSuppliedArguments() and
|
||||
used >= supplied
|
||||
select format, "Argument '{" + used + "}' has not been supplied to $@ format string.", src, "this"
|
||||
|
|
|
@ -13,6 +13,8 @@ import csharp
|
|||
import semmle.code.csharp.frameworks.Format
|
||||
|
||||
from FormatCall format, int unused, ValidFormatString src
|
||||
where src = format.getAFormatSource()
|
||||
and unused = format.getAnUnusedArgument(src)
|
||||
select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused), "this supplied value"
|
||||
where
|
||||
src = format.getAFormatSource() and
|
||||
unused = format.getAnUnusedArgument(src)
|
||||
select format, "The $@ ignores $@.", src, "format string", format.getSuppliedExpr(unused),
|
||||
"this supplied value"
|
||||
|
|
|
@ -10,22 +10,25 @@
|
|||
* maintainability
|
||||
* external/cwe/cwe-581
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
from Class c, Method present, string missing
|
||||
where c.isSourceDeclaration() and
|
||||
where
|
||||
c.isSourceDeclaration() and
|
||||
(
|
||||
(
|
||||
present = (EqualsMethod)c.getAMethod() and
|
||||
present = c.getAMethod().(EqualsMethod) and
|
||||
not c.getAMethod() instanceof GetHashCodeMethod and
|
||||
missing = "GetHashCode()"
|
||||
) or
|
||||
)
|
||||
or
|
||||
(
|
||||
present = (GetHashCodeMethod)c.getAMethod() and
|
||||
present = c.getAMethod().(GetHashCodeMethod) and
|
||||
not implementsEquals(c) and
|
||||
missing = "Equals(object)"
|
||||
)
|
||||
)
|
||||
select c, "Class '" + c.getName() + "' overrides $@, but not " + missing + ".",
|
||||
present, present.getName()
|
||||
select c, "Class '" + c.getName() + "' overrides $@, but not " + missing + ".", present,
|
||||
present.getName()
|
||||
|
|
|
@ -13,8 +13,7 @@ import csharp
|
|||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
predicate implementsIComparable(ValueOrRefType t, Type paramType) {
|
||||
exists(ConstructedType ct |
|
||||
t.getABaseType+() = ct |
|
||||
exists(ConstructedType ct | t.getABaseType+() = ct |
|
||||
ct = any(SystemIComparableTInterface i).getAConstructedGeneric() and
|
||||
paramType = ct.getATypeArgument()
|
||||
)
|
||||
|
@ -28,20 +27,21 @@ predicate implementsIComparable(ValueOrRefType t, Type paramType) {
|
|||
}
|
||||
|
||||
predicate compareToMethod(Method m, Type paramType) {
|
||||
m.hasName("CompareTo")
|
||||
and m.fromSource()
|
||||
and m.isPublic()
|
||||
and m.getReturnType() instanceof IntType
|
||||
and m.getNumberOfParameters() = 1
|
||||
and paramType = m.getAParameter().getType()
|
||||
m.hasName("CompareTo") and
|
||||
m.fromSource() and
|
||||
m.isPublic() and
|
||||
m.getReturnType() instanceof IntType and
|
||||
m.getNumberOfParameters() = 1 and
|
||||
paramType = m.getAParameter().getType()
|
||||
}
|
||||
|
||||
from Method m, RefType declaringType, Type actualParamType
|
||||
where m.isSourceDeclaration()
|
||||
and declaringType = m.getDeclaringType()
|
||||
and compareToMethod(m, actualParamType)
|
||||
and not implementsIComparable(declaringType, actualParamType)
|
||||
select m, "The parameter of this 'CompareTo' method is of type $@, but $@ does not implement 'IComparable<$@>'.",
|
||||
actualParamType, actualParamType.getName(),
|
||||
declaringType, declaringType.getName(),
|
||||
where
|
||||
m.isSourceDeclaration() and
|
||||
declaringType = m.getDeclaringType() and
|
||||
compareToMethod(m, actualParamType) and
|
||||
not implementsIComparable(declaringType, actualParamType)
|
||||
select m,
|
||||
"The parameter of this 'CompareTo' method is of type $@, but $@ does not implement 'IComparable<$@>'.",
|
||||
actualParamType, actualParamType.getName(), declaringType, declaringType.getName(),
|
||||
actualParamType, actualParamType.getName()
|
||||
|
|
|
@ -14,21 +14,22 @@ import semmle.code.csharp.frameworks.System
|
|||
|
||||
class EqualsOtherMethod extends Method {
|
||||
EqualsOtherMethod() {
|
||||
this.hasName("Equals")
|
||||
and this.getNumberOfParameters() = 1
|
||||
and this.getReturnType() instanceof BoolType
|
||||
and this.getDeclaringType() instanceof Class
|
||||
and not this instanceof EqualsMethod
|
||||
and not this instanceof IEquatableEqualsMethod
|
||||
this.hasName("Equals") and
|
||||
this.getNumberOfParameters() = 1 and
|
||||
this.getReturnType() instanceof BoolType and
|
||||
this.getDeclaringType() instanceof Class and
|
||||
not this instanceof EqualsMethod and
|
||||
not this instanceof IEquatableEqualsMethod
|
||||
}
|
||||
|
||||
Type getType() {
|
||||
result = this.getParameter(0).getType()
|
||||
}
|
||||
Type getType() { result = this.getParameter(0).getType() }
|
||||
}
|
||||
|
||||
from EqualsOtherMethod equalsOther
|
||||
where equalsOther.isSourceDeclaration()
|
||||
and not implementsEquals(equalsOther.getDeclaringType())
|
||||
select equalsOther, "The $@ of this 'Equals(" + equalsOther.getType().getName() + ")' method does not override 'Equals(object)'.",
|
||||
equalsOther.getDeclaringType(), "declaring type"
|
||||
where
|
||||
equalsOther.isSourceDeclaration() and
|
||||
not implementsEquals(equalsOther.getDeclaringType())
|
||||
select equalsOther,
|
||||
"The $@ of this 'Equals(" + equalsOther.getType().getName() +
|
||||
")' method does not override 'Equals(object)'.", equalsOther.getDeclaringType(),
|
||||
"declaring type"
|
||||
|
|
|
@ -17,15 +17,16 @@ import Dispose
|
|||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
from DisposableType t, DisposableField f, Method dispose
|
||||
where f.getDeclaringType() = t
|
||||
and not f.isStatic()
|
||||
and t.isSourceDeclaration()
|
||||
and dispose = getInvokedDisposeMethod(t)
|
||||
and dispose.getDeclaringType() = t
|
||||
and not exists(MethodCall mc |
|
||||
mc.getTarget() instanceof DisposeMethod
|
||||
and mc.getQualifier() = f.getAnAccess()
|
||||
and mc.getEnclosingCallable() = dispose
|
||||
where
|
||||
f.getDeclaringType() = t and
|
||||
not f.isStatic() and
|
||||
t.isSourceDeclaration() and
|
||||
dispose = getInvokedDisposeMethod(t) and
|
||||
dispose.getDeclaringType() = t and
|
||||
not exists(MethodCall mc |
|
||||
mc.getTarget() instanceof DisposeMethod and
|
||||
mc.getQualifier() = f.getAnAccess() and
|
||||
mc.getEnclosingCallable() = dispose
|
||||
)
|
||||
select dispose, "This 'Dispose()' method does not call 'Dispose()' on `IDisposable` field $@.",
|
||||
f, f.getName()
|
||||
select dispose, "This 'Dispose()' method does not call 'Dispose()' on `IDisposable` field $@.", f,
|
||||
f.getName()
|
||||
|
|
|
@ -17,10 +17,10 @@ import Dispose
|
|||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
from DisposableType t, DisposableField f
|
||||
where f.getDeclaringType() = t
|
||||
and t.isSourceDeclaration()
|
||||
and not f.isStatic()
|
||||
and not implementsDispose(t)
|
||||
and not isAutoDisposedWebControl(f)
|
||||
select t, "This type does not override 'Dispose()' but has disposable field $@.",
|
||||
f, f.getName()
|
||||
where
|
||||
f.getDeclaringType() = t and
|
||||
t.isSourceDeclaration() and
|
||||
not f.isStatic() and
|
||||
not implementsDispose(t) and
|
||||
not isAutoDisposedWebControl(f)
|
||||
select t, "This type does not override 'Dispose()' but has disposable field $@.", f, f.getName()
|
||||
|
|
|
@ -22,55 +22,57 @@ import semmle.code.csharp.commons.Disposal
|
|||
/** Holds if expression `e` escapes the local method scope. */
|
||||
predicate escapes(Expr e) {
|
||||
// Things that return escape
|
||||
exists(Callable c | c.canReturn(e) or c.canYieldReturn(e)) or
|
||||
exists(Callable c | c.canReturn(e) or c.canYieldReturn(e))
|
||||
or
|
||||
// Things that are assigned to fields, properties, or indexers escape the scope
|
||||
exists(AssignableDefinition def, Assignable a |
|
||||
def.getSource() = e and
|
||||
a = def.getTarget() |
|
||||
a = def.getTarget()
|
||||
|
|
||||
a instanceof Field or
|
||||
a instanceof Property or
|
||||
a instanceof Indexer
|
||||
) or
|
||||
// Things that are added to a collection of some kind are likely to escape the scope
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().hasName("Add") |
|
||||
mc.getAnArgument() = e
|
||||
)
|
||||
or
|
||||
// Things that are added to a collection of some kind are likely to escape the scope
|
||||
exists(MethodCall mc | mc.getTarget().hasName("Add") | mc.getAnArgument() = e)
|
||||
}
|
||||
|
||||
/** Holds if the `disposable` is a whitelisted result. */
|
||||
predicate isWhitelisted(LocalScopeDisposableCreation disposable) {
|
||||
exists(MethodCall mc |
|
||||
// Close can often be used instead of Dispose
|
||||
mc.getTarget().hasName("Close") or
|
||||
mc.getTarget().hasName("Close")
|
||||
or
|
||||
// Used as an alias for Dispose
|
||||
mc.getTarget().hasName("Clear")
|
||||
|
|
||||
|
|
||||
mc.getQualifier() = disposable.getADisposeTarget()
|
||||
) or
|
||||
)
|
||||
or
|
||||
// WebControls are usually disposed automatically
|
||||
disposable.getType() instanceof WebControl
|
||||
}
|
||||
|
||||
from LocalScopeDisposableCreation disposable
|
||||
// The disposable is local scope - the lifetime is the execution of this method
|
||||
where not escapes(disposable.getADisposeTarget())
|
||||
// The disposable is local scope - the lifetime is the execution of this method
|
||||
where
|
||||
not escapes(disposable.getADisposeTarget()) and
|
||||
// Only care about library types - user types often have spurious IDisposable declarations
|
||||
and disposable.getType().fromLibrary()
|
||||
disposable.getType().fromLibrary() and
|
||||
// Disposables constructed in the initializer of a `using` are safe
|
||||
and not exists(UsingStmt us | us.getAnExpr() = disposable.getADisposeTarget())
|
||||
not exists(UsingStmt us | us.getAnExpr() = disposable.getADisposeTarget()) and
|
||||
// Foreach calls Dispose
|
||||
and not exists(ForeachStmt fs | fs.getIterableExpr() = disposable.getADisposeTarget())
|
||||
not exists(ForeachStmt fs | fs.getIterableExpr() = disposable.getADisposeTarget()) and
|
||||
// As are disposables on which the Dispose method is called explicitly
|
||||
and not exists(MethodCall mc |
|
||||
mc.getTarget() instanceof DisposeMethod
|
||||
and mc.getQualifier() = disposable.getADisposeTarget()
|
||||
)
|
||||
not exists(MethodCall mc |
|
||||
mc.getTarget() instanceof DisposeMethod and
|
||||
mc.getQualifier() = disposable.getADisposeTarget()
|
||||
) and
|
||||
// Ignore whitelisted results
|
||||
and not isWhitelisted(disposable)
|
||||
not isWhitelisted(disposable) and
|
||||
// Not passed to a disposing method
|
||||
and not exists(Call c, Parameter p |
|
||||
disposable.getADisposeTarget() = c.getArgumentForParameter(p) |
|
||||
not exists(Call c, Parameter p | disposable.getADisposeTarget() = c.getArgumentForParameter(p) |
|
||||
mayBeDisposed(p)
|
||||
)
|
||||
select disposable, "Disposable '" + disposable.getType() + "' is created here but is not disposed."
|
||||
|
|
|
@ -21,23 +21,24 @@ private predicate potentialOverride(Method vm, Method m) {
|
|||
* but does not do so.
|
||||
*/
|
||||
predicate nonOverridingMethod(Method m, Method vm) {
|
||||
vm.isVirtual()
|
||||
and not vm.isOverride()
|
||||
and not vm.overrides()
|
||||
and potentialOverride(vm, m)
|
||||
and not m.overrides()
|
||||
and not m.isOverride()
|
||||
and not m.isNew()
|
||||
and m=m.getSourceDeclaration()
|
||||
and m.getNumberOfParameters() = vm.getNumberOfParameters()
|
||||
and forall(int i, Parameter p1, Parameter p2 |
|
||||
p1=m.getParameter(i) and p2=vm.getParameter(i) |
|
||||
p1.getType() = p2.getType())
|
||||
and m.getName().toLowerCase() = vm.getName().toLowerCase()
|
||||
vm.isVirtual() and
|
||||
not vm.isOverride() and
|
||||
not vm.overrides() and
|
||||
potentialOverride(vm, m) and
|
||||
not m.overrides() and
|
||||
not m.isOverride() and
|
||||
not m.isNew() and
|
||||
m = m.getSourceDeclaration() and
|
||||
m.getNumberOfParameters() = vm.getNumberOfParameters() and
|
||||
forall(int i, Parameter p1, Parameter p2 | p1 = m.getParameter(i) and p2 = vm.getParameter(i) |
|
||||
p1.getType() = p2.getType()
|
||||
) and
|
||||
m.getName().toLowerCase() = vm.getName().toLowerCase()
|
||||
}
|
||||
|
||||
from Method m, Method vm
|
||||
where m.fromSource()
|
||||
and nonOverridingMethod(m, vm)
|
||||
where
|
||||
m.fromSource() and
|
||||
nonOverridingMethod(m, vm)
|
||||
select m, "Method '" + m.getName() + "' looks like it should override $@ but does not do so.",
|
||||
vm.getSourceDeclaration(), vm.getQualifiedName()
|
||||
|
|
|
@ -14,7 +14,8 @@ import csharp
|
|||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
from MethodCall c, EqualsMethod equals
|
||||
where c.getTarget().getSourceDeclaration() = equals
|
||||
and c.getArgument(0) instanceof NullLiteral
|
||||
and not c.getQualifier().getType() instanceof NullableType
|
||||
where
|
||||
c.getTarget().getSourceDeclaration() = equals and
|
||||
c.getArgument(0) instanceof NullLiteral and
|
||||
not c.getQualifier().getType() instanceof NullableType
|
||||
select c, "Equality test with 'null' will never be true, but may throw a 'NullReferenceException'."
|
||||
|
|
|
@ -12,19 +12,18 @@
|
|||
* statistical
|
||||
* non-attributable
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.system.IO
|
||||
import semmle.code.csharp.Chaining
|
||||
|
||||
/** Holds if `m` is a method whose return value should always be checked. */
|
||||
predicate important(Method m) {
|
||||
exists(Method read |
|
||||
read = any(SystemIOStreamClass c).getReadMethod() |
|
||||
exists(Method read | read = any(SystemIOStreamClass c).getReadMethod() |
|
||||
m = read.getAnOverrider*()
|
||||
)
|
||||
or
|
||||
exists(Method readByte |
|
||||
readByte = any(SystemIOStreamClass c).getReadByteMethod() |
|
||||
exists(Method readByte | readByte = any(SystemIOStreamClass c).getReadByteMethod() |
|
||||
m = readByte.getAnOverrider*()
|
||||
)
|
||||
// add more ...
|
||||
|
@ -49,14 +48,14 @@ predicate dubious(Method m, int percentage) {
|
|||
exists(int used, int total, Method target |
|
||||
target = m.getSourceDeclaration() and
|
||||
used = count(MethodCall mc |
|
||||
mc.getTarget().getSourceDeclaration() = target and
|
||||
not mc instanceof DiscardedMethodCall and
|
||||
(methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType())
|
||||
) and
|
||||
mc.getTarget().getSourceDeclaration() = target and
|
||||
not mc instanceof DiscardedMethodCall and
|
||||
(methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType())
|
||||
) and
|
||||
total = count(MethodCall mc |
|
||||
mc.getTarget().getSourceDeclaration() = target and
|
||||
(methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType())
|
||||
) and
|
||||
mc.getTarget().getSourceDeclaration() = target and
|
||||
(methodHasGenericReturnType(m) implies m.getReturnType() = mc.getTarget().getReturnType())
|
||||
) and
|
||||
used != total and
|
||||
percentage = used * 100 / total and
|
||||
percentage >= 90 and
|
||||
|
@ -66,9 +65,9 @@ predicate dubious(Method m, int percentage) {
|
|||
|
||||
int chainedUses(Method m) {
|
||||
result = count(MethodCall mc, MethodCall qual |
|
||||
m = mc.getTarget() and
|
||||
hasQualifierAndTarget(mc, qual, qual.getTarget())
|
||||
)
|
||||
m = mc.getTarget() and
|
||||
hasQualifierAndTarget(mc, qual, qual.getTarget())
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasQualifierAndTarget(MethodCall mc, Expr qualifier, Method m) {
|
||||
|
@ -78,10 +77,11 @@ predicate hasQualifierAndTarget(MethodCall mc, Expr qualifier, Method m) {
|
|||
|
||||
/** Holds if `m` is a white-listed method where checking the return value is not required. */
|
||||
predicate whitelist(Method m) {
|
||||
m.hasName("TryGetValue") or
|
||||
m.hasName("TryParse") or
|
||||
exists(Namespace n |
|
||||
n = m.getDeclaringType().getNamespace().getParentNamespace*() |
|
||||
m.hasName("TryGetValue")
|
||||
or
|
||||
m.hasName("TryParse")
|
||||
or
|
||||
exists(Namespace n | n = m.getDeclaringType().getNamespace().getParentNamespace*() |
|
||||
n.getName().regexpMatch("(Fluent)?NHibernate") or
|
||||
n.getName() = "Moq"
|
||||
)
|
||||
|
@ -89,9 +89,7 @@ predicate whitelist(Method m) {
|
|||
}
|
||||
|
||||
class DiscardedMethodCall extends MethodCall {
|
||||
DiscardedMethodCall() {
|
||||
this.getParent() instanceof ExprStmt
|
||||
}
|
||||
DiscardedMethodCall() { this.getParent() instanceof ExprStmt }
|
||||
|
||||
string query() {
|
||||
exists(Method m |
|
||||
|
@ -99,11 +97,11 @@ class DiscardedMethodCall extends MethodCall {
|
|||
not whitelist(m) and
|
||||
// Do not alert on "void wrapper methods", i.e., methods that are inserted
|
||||
// to deliberately ignore the returned value
|
||||
not getEnclosingCallable().getStatementBody().getNumberOfStmts() = 1 |
|
||||
not getEnclosingCallable().getStatementBody().getNumberOfStmts() = 1
|
||||
|
|
||||
(important(m) and result = "should always be checked")
|
||||
or
|
||||
exists(int percentage |
|
||||
dubious(m, percentage) |
|
||||
exists(int percentage | dubious(m, percentage) |
|
||||
result = percentage.toString() + "% of calls to this method have their result used"
|
||||
)
|
||||
)
|
||||
|
|
|
@ -12,6 +12,5 @@
|
|||
import semmle.code.asp.AspNet
|
||||
|
||||
from AspText text
|
||||
where
|
||||
exists(text.getBody().regexpFind("\\w{3,}", _, _))
|
||||
where exists(text.getBody().regexpFind("\\w{3,}", _, _))
|
||||
select text, "This text has not been internationalized."
|
||||
|
|
|
@ -12,6 +12,5 @@
|
|||
import semmle.code.asp.AspNet
|
||||
|
||||
from AspCode code
|
||||
where
|
||||
exists(code.getBody().regexpFind("(Then|\\{)\\s*$",_,_))
|
||||
where exists(code.getBody().regexpFind("(Then|\\{)\\s*$", _, _))
|
||||
select code, "Split control structure."
|
||||
|
|
|
@ -14,8 +14,7 @@ class SuppressionComment extends SinglelineComment {
|
|||
string annotation;
|
||||
|
||||
SuppressionComment() {
|
||||
exists(string text |
|
||||
text = this.getText() |
|
||||
exists(string text | text = this.getText() |
|
||||
// match `lgtm[...]` anywhere in the comment
|
||||
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
|
||||
or
|
||||
|
@ -25,57 +24,49 @@ class SuppressionComment extends SinglelineComment {
|
|||
}
|
||||
|
||||
/** Gets the suppression annotation in this comment. */
|
||||
string getAnnotation() {
|
||||
result = annotation
|
||||
}
|
||||
string getAnnotation() { result = annotation }
|
||||
|
||||
/**
|
||||
* Holds if this comment applies to the range from column `startcolumn` of line `startline`
|
||||
* to column `endcolumn` of line `endline` in file `filepath`.
|
||||
*/
|
||||
* Holds if this comment applies to the range from column `startcolumn` of line `startline`
|
||||
* to column `endcolumn` of line `endline` in file `filepath`.
|
||||
*/
|
||||
predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
|
||||
startcolumn = 1
|
||||
}
|
||||
|
||||
/** Gets the scope of this suppression. */
|
||||
SuppressionScope getScope() {
|
||||
this = result.getSuppressionComment()
|
||||
}
|
||||
SuppressionScope getScope() { this = result.getSuppressionComment() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The scope of an alert suppression comment.
|
||||
*/
|
||||
class SuppressionScope extends @commentline {
|
||||
SuppressionScope() {
|
||||
this instanceof SuppressionComment
|
||||
}
|
||||
SuppressionScope() { this instanceof SuppressionComment }
|
||||
|
||||
/** Gets a suppression comment with this scope. */
|
||||
SuppressionComment getSuppressionComment() {
|
||||
result = this
|
||||
}
|
||||
SuppressionComment getSuppressionComment() { result = this }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [LGTM locations](https://lgtm.com/help/ql/locations).
|
||||
*/
|
||||
predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [LGTM locations](https://lgtm.com/help/ql/locations).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
result = "suppression range"
|
||||
}
|
||||
string toString() { result = "suppression range" }
|
||||
}
|
||||
|
||||
from SuppressionComment c
|
||||
select c, // suppression comment
|
||||
c.getText(), // text of suppression comment (excluding delimiters)
|
||||
c.getAnnotation(), // text of suppression annotation
|
||||
c.getScope() // scope of suppression
|
||||
select c, // suppression comment
|
||||
c.getText(), // text of suppression comment (excluding delimiters)
|
||||
c.getAnnotation(), // text of suppression annotation
|
||||
c.getScope() // scope of suppression
|
||||
|
|
|
@ -15,32 +15,27 @@ import semmle.code.csharp.metrics.Coupling
|
|||
|
||||
/** inner is nested (possibly more than one level deep) within outer */
|
||||
predicate nestedWithin(ValueOrRefType outer, NestedType inner) {
|
||||
inner.getDeclaringType() = outer
|
||||
or nestedWithin(outer, inner.getDeclaringType())
|
||||
inner.getDeclaringType() = outer or
|
||||
nestedWithin(outer, inner.getDeclaringType())
|
||||
}
|
||||
|
||||
from ValueOrRefType t1, ValueOrRefType t2
|
||||
where
|
||||
t1 != t2
|
||||
and depends(t1, t2)
|
||||
and depends(t2, t1)
|
||||
|
||||
t1 != t2 and
|
||||
depends(t1, t2) and
|
||||
depends(t2, t1) and
|
||||
// PREVENT SYMMETRICAL RESULTS
|
||||
and t1.getName() < t2.getName()
|
||||
|
||||
t1.getName() < t2.getName() and
|
||||
// ADDITIONAL CONSTRAINTS
|
||||
and t1.fromSource()
|
||||
and t2.fromSource()
|
||||
|
||||
t1.fromSource() and
|
||||
t2.fromSource() and
|
||||
// EXCLUSIONS
|
||||
and not
|
||||
(
|
||||
nestedWithin(t1, t2)
|
||||
or nestedWithin(t2, t1)
|
||||
or t1.getName().toLowerCase().matches("%visitor%")
|
||||
or t2.getName().toLowerCase().matches("%visitor%")
|
||||
or t1.getAMember().getName().toLowerCase().matches("%visit%")
|
||||
or t2.getAMember().getName().toLowerCase().matches("%visit%")
|
||||
not (
|
||||
nestedWithin(t1, t2) or
|
||||
nestedWithin(t2, t1) or
|
||||
t1.getName().toLowerCase().matches("%visitor%") or
|
||||
t2.getName().toLowerCase().matches("%visitor%") or
|
||||
t1.getAMember().getName().toLowerCase().matches("%visit%") or
|
||||
t2.getAMember().getName().toLowerCase().matches("%visit%")
|
||||
)
|
||||
select t1, "This type and type $@ are mutually dependent.",
|
||||
t2, t2.getName()
|
||||
select t1, "This type and type $@ are mutually dependent.", t2, t2.getName()
|
||||
|
|
|
@ -11,31 +11,24 @@
|
|||
* maintainability
|
||||
* modularity
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
Member getAUsedMember(Method m) {
|
||||
exists(MemberAccess ma |
|
||||
ma.getEnclosingCallable() = m |
|
||||
exists(MemberAccess ma | ma.getEnclosingCallable() = m |
|
||||
result = ma.getTarget().getSourceDeclaration()
|
||||
)
|
||||
or
|
||||
exists(Call c |
|
||||
c.getEnclosingCallable() = m |
|
||||
result = c.getTarget().getSourceDeclaration()
|
||||
)
|
||||
exists(Call c | c.getEnclosingCallable() = m | result = c.getTarget().getSourceDeclaration())
|
||||
}
|
||||
|
||||
int dependencyCount(Method source, RefType target) {
|
||||
result = strictcount(Member m | m = getAUsedMember(source) and m = target.getAMember())
|
||||
}
|
||||
|
||||
predicate methodDependsOn(Method m, RefType target) {
|
||||
exists(dependencyCount(m, target))
|
||||
}
|
||||
predicate methodDependsOn(Method m, RefType target) { exists(dependencyCount(m, target)) }
|
||||
|
||||
predicate dependsOn(RefType source, RefType target) {
|
||||
methodDependsOn(source.getAMethod(), target)
|
||||
}
|
||||
predicate dependsOn(RefType source, RefType target) { methodDependsOn(source.getAMethod(), target) }
|
||||
|
||||
int selfDependencyCount(Method source) {
|
||||
result = sum(dependencyCount(source, source.getDeclaringType+()))
|
||||
|
@ -44,12 +37,12 @@ int selfDependencyCount(Method source) {
|
|||
predicate dependsHighlyOn(Method source, RefType target, int selfCount, int depCount) {
|
||||
depCount = dependencyCount(source, target) and
|
||||
selfCount = selfDependencyCount(source) and
|
||||
depCount > 2*selfCount and
|
||||
depCount > 2 * selfCount and
|
||||
depCount > 4
|
||||
}
|
||||
|
||||
predicate query(Method m, RefType targetType, int selfCount, int depCount) {
|
||||
exists (RefType sourceType | sourceType = m.getDeclaringType() |
|
||||
exists(RefType sourceType | sourceType = m.getDeclaringType() |
|
||||
dependsHighlyOn(m, targetType, selfCount, depCount) and
|
||||
// Interfaces are depended upon by their very nature
|
||||
not targetType instanceof Interface and
|
||||
|
@ -63,8 +56,7 @@ predicate query(Method m, RefType targetType, int selfCount, int depCount) {
|
|||
// Do not move between nested types
|
||||
not (sourceType.getDeclaringType*() = targetType or targetType.getDeclaringType*() = sourceType) and
|
||||
// Check that the target type already depends on every type used by the method
|
||||
forall(RefType dependency |
|
||||
methodDependsOn(m, dependency) |
|
||||
forall(RefType dependency | methodDependsOn(m, dependency) |
|
||||
dependsOn(targetType, dependency) or
|
||||
targetType = dependency or
|
||||
dependency.getNamespace().hasName("System")
|
||||
|
@ -73,10 +65,12 @@ predicate query(Method m, RefType targetType, int selfCount, int depCount) {
|
|||
}
|
||||
|
||||
from Method m, RefType other, int selfCount, int depCount
|
||||
where query(m, other, selfCount, depCount) and
|
||||
// Don't include types that are used from many different places - we only highlight
|
||||
// relatively local fixes that could reasonably be implemented.
|
||||
count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10
|
||||
select m, "Method " + m.getName() + " is too closely tied to $@: " + depCount +
|
||||
" dependencies to it, but only " + selfCount + " dependencies to its own type.",
|
||||
other, other.getName()
|
||||
where
|
||||
query(m, other, selfCount, depCount) and
|
||||
// Don't include types that are used from many different places - we only highlight
|
||||
// relatively local fixes that could reasonably be implemented.
|
||||
count(Method yetAnotherMethod | query(yetAnotherMethod, other, _, _)) < 10
|
||||
select m,
|
||||
"Method " + m.getName() + " is too closely tied to $@: " + depCount +
|
||||
" dependencies to it, but only " + selfCount + " dependencies to its own type.", other,
|
||||
other.getName()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* @tags maintainability
|
||||
* modularity
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate enclosingRefType(Variable v, RefType type) {
|
||||
|
@ -45,16 +46,19 @@ predicate dependencyCount(RefType source, RefType target, int res) {
|
|||
exists(int varCount, int funCount |
|
||||
variableDependencyCount(source, target, varCount) and
|
||||
functionDependencyCount(source, target, funCount) and
|
||||
res = varCount + funCount
|
||||
and res > 15)
|
||||
res = varCount + funCount and
|
||||
res > 15
|
||||
)
|
||||
}
|
||||
|
||||
from RefType a, RefType b, int ca, int cb
|
||||
where dependencyCount(a, b, ca) and
|
||||
dependencyCount(b, a, cb) and
|
||||
ca > 15 and
|
||||
cb > 15 and
|
||||
ca >= cb and
|
||||
a != b
|
||||
select a, "Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() +
|
||||
" dependencies one way and " + cb.toString() + " the other).", b, b.getName()
|
||||
where
|
||||
dependencyCount(a, b, ca) and
|
||||
dependencyCount(b, a, cb) and
|
||||
ca > 15 and
|
||||
cb > 15 and
|
||||
ca >= cb and
|
||||
a != b
|
||||
select a,
|
||||
"Type " + a.getName() + " is too closely tied to $@ (" + ca.toString() +
|
||||
" dependencies one way and " + cb.toString() + " the other).", b, b.getName()
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
import csharp
|
||||
|
||||
from Class c, Method m, MethodCall call
|
||||
where m.isExtern()
|
||||
and m.getDeclaringType() = c
|
||||
and call.getTarget() = m
|
||||
where
|
||||
m.isExtern() and
|
||||
m.getDeclaringType() = c and
|
||||
call.getTarget() = m
|
||||
select call, "Replace this call with a call to managed code if possible."
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* correctness
|
||||
* external/cwe/cwe-395
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from SpecificCatchClause scc
|
||||
|
|
|
@ -12,12 +12,10 @@
|
|||
|
||||
import csharp
|
||||
|
||||
class CommentedOutCode extends CommentBlock
|
||||
{
|
||||
CommentedOutCode()
|
||||
{
|
||||
class CommentedOutCode extends CommentBlock {
|
||||
CommentedOutCode() {
|
||||
not isXmlCommentBlock() and
|
||||
2*count(getAProbableCodeLine()) > count(getANonEmptyLine())
|
||||
2 * count(getAProbableCodeLine()) > count(getANonEmptyLine())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* @tags maintainability
|
||||
* external/cwe/cwe-546
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from CommentLine c
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
* readability
|
||||
* external/cwe/cwe-835
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Assertions
|
||||
import semmle.code.csharp.commons.Constants
|
||||
|
@ -28,13 +29,9 @@ abstract class ConstantCondition extends Expr {
|
|||
class ConstantBooleanCondition extends ConstantCondition {
|
||||
boolean b;
|
||||
|
||||
ConstantBooleanCondition() {
|
||||
isConstantCondition(this, b)
|
||||
}
|
||||
ConstantBooleanCondition() { isConstantCondition(this, b) }
|
||||
|
||||
override string getMessage() {
|
||||
result = "Condition always evaluates to '" + b + "'."
|
||||
}
|
||||
override string getMessage() { result = "Condition always evaluates to '" + b + "'." }
|
||||
|
||||
override predicate isWhiteListed() {
|
||||
// E.g. `x ?? false`
|
||||
|
@ -60,9 +57,7 @@ class ConstantIfCondition extends ConstantBooleanCondition {
|
|||
|
||||
/** A constant loop condition. */
|
||||
class ConstantLoopCondition extends ConstantBooleanCondition {
|
||||
ConstantLoopCondition() {
|
||||
this = any(LoopStmt ls).getCondition()
|
||||
}
|
||||
ConstantLoopCondition() { this = any(LoopStmt ls).getCondition() }
|
||||
|
||||
override predicate isWhiteListed() {
|
||||
// Clearly intentional infinite loops are allowed
|
||||
|
@ -75,10 +70,8 @@ class ConstantNullnessCondition extends ConstantCondition {
|
|||
boolean b;
|
||||
|
||||
ConstantNullnessCondition() {
|
||||
forex(ControlFlow::Node cfn |
|
||||
cfn = this.getAControlFlowNode() |
|
||||
exists(ControlFlow::SuccessorTypes::NullnessSuccessor t |
|
||||
exists(cfn.getASuccessorByType(t)) |
|
||||
forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() |
|
||||
exists(ControlFlow::SuccessorTypes::NullnessSuccessor t | exists(cfn.getASuccessorByType(t)) |
|
||||
b = t.getValue()
|
||||
) and
|
||||
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
|
||||
|
@ -86,10 +79,9 @@ class ConstantNullnessCondition extends ConstantCondition {
|
|||
}
|
||||
|
||||
override string getMessage() {
|
||||
if b = true then
|
||||
result = "Expression is always 'null'."
|
||||
else
|
||||
result = "Expression is never 'null'."
|
||||
if b = true
|
||||
then result = "Expression is always 'null'."
|
||||
else result = "Expression is never 'null'."
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,10 +90,8 @@ class ConstantMatchingCondition extends ConstantCondition {
|
|||
boolean b;
|
||||
|
||||
ConstantMatchingCondition() {
|
||||
forex(ControlFlow::Node cfn |
|
||||
cfn = this.getAControlFlowNode() |
|
||||
exists(ControlFlow::SuccessorTypes::MatchingSuccessor t |
|
||||
exists(cfn.getASuccessorByType(t)) |
|
||||
forex(ControlFlow::Node cfn | cfn = this.getAControlFlowNode() |
|
||||
exists(ControlFlow::SuccessorTypes::MatchingSuccessor t | exists(cfn.getASuccessorByType(t)) |
|
||||
b = t.getValue()
|
||||
) and
|
||||
strictcount(ControlFlow::SuccessorType t | exists(cfn.getASuccessorByType(t))) = 1
|
||||
|
@ -109,15 +99,13 @@ class ConstantMatchingCondition extends ConstantCondition {
|
|||
}
|
||||
|
||||
override string getMessage() {
|
||||
if b = true then
|
||||
result = "Pattern always matches."
|
||||
else
|
||||
result = "Pattern never matches."
|
||||
if b = true then result = "Pattern always matches." else result = "Pattern never matches."
|
||||
}
|
||||
}
|
||||
|
||||
from ConstantCondition c, string msg
|
||||
where msg = c.getMessage()
|
||||
and not c.isWhiteListed()
|
||||
and not isExprInAssertion(c)
|
||||
where
|
||||
msg = c.getMessage() and
|
||||
not c.isWhiteListed() and
|
||||
not isExprInAssertion(c)
|
||||
select c, msg
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
import csharp
|
||||
|
||||
from Interface i
|
||||
where not exists(i.getAMember())
|
||||
and i.isSourceDeclaration()
|
||||
and count(Interface base | i.getABaseInterface() = base) <= 1
|
||||
where
|
||||
not exists(i.getAMember()) and
|
||||
i.isSourceDeclaration() and
|
||||
count(Interface base | i.getABaseInterface() = base) <= 1
|
||||
select i, "Interface '" + i.getName() + "' does not declare any members."
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
* @tags maintainability
|
||||
* readability
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
private string localVarInType(ValueOrRefType t, LocalScopeVariable v) {
|
||||
v.getCallable().getDeclaringType() = t and
|
||||
result = v.getName() and
|
||||
|
@ -28,12 +29,10 @@ private string memberInType(ValueOrRefType t, Member m) {
|
|||
}
|
||||
|
||||
private predicate acceptableShadowing(LocalScopeVariable v, Member m) {
|
||||
exists(ValueOrRefType t |
|
||||
localVarInType(t, v) = memberInType(t, m) |
|
||||
exists(ValueOrRefType t | localVarInType(t, v) = memberInType(t, m) |
|
||||
// If the callable declaring the local also accesses the shadowed member
|
||||
// using an explicit `this` qualifier, the shadowing is likely deliberate.
|
||||
exists(MemberAccess ma |
|
||||
ma.getTarget() = m |
|
||||
exists(MemberAccess ma | ma.getTarget() = m |
|
||||
ma.getEnclosingCallable() = v.getCallable() and
|
||||
ma.targetIsLocalInstance() and
|
||||
not ma.getQualifier().isImplicit()
|
||||
|
@ -49,7 +48,9 @@ private predicate shadowing(ValueOrRefType t, LocalScopeVariable v, Member m) {
|
|||
}
|
||||
|
||||
from LocalScopeVariable v, Callable c, ValueOrRefType t, Member m
|
||||
where c = v.getCallable()
|
||||
and shadowing(t, v, m)
|
||||
and (c.(Modifiable).isStatic() implies m.isStatic())
|
||||
select v, "Local scope variable '" + v.getName() + "' shadows $@.", m, t.getName() + "." + m.getName()
|
||||
where
|
||||
c = v.getCallable() and
|
||||
shadowing(t, v, m) and
|
||||
(c.(Modifiable).isStatic() implies m.isStatic())
|
||||
select v, "Local scope variable '" + v.getName() + "' shadows $@.", m,
|
||||
t.getName() + "." + m.getName()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* @tags maintainability
|
||||
* modularity
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
class ConstantField extends Field {
|
||||
|
@ -20,11 +21,11 @@ class ConstantField extends Field {
|
|||
}
|
||||
|
||||
from Class c
|
||||
where c.isSourceDeclaration()
|
||||
and c.isAbstract()
|
||||
and c.getAMember() instanceof ConstantField
|
||||
and forex(Member m |
|
||||
m = c.getAMember() |
|
||||
where
|
||||
c.isSourceDeclaration() and
|
||||
c.isAbstract() and
|
||||
c.getAMember() instanceof ConstantField and
|
||||
forex(Member m | m = c.getAMember() |
|
||||
m instanceof ConstantField or
|
||||
m instanceof Constructor
|
||||
)
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
import csharp
|
||||
|
||||
from Method m, int n
|
||||
where m.isSourceDeclaration()
|
||||
and n = count(Parameter p | p = m.getAParameter() and p.isRef())
|
||||
and n > 2
|
||||
select m, "Method '" + m.getName() + "' has " + n + " 'ref' parameters and might be hard to understand."
|
||||
where
|
||||
m.isSourceDeclaration() and
|
||||
n = count(Parameter p | p = m.getAParameter() and p.isRef()) and
|
||||
n > 2
|
||||
select m,
|
||||
"Method '" + m.getName() + "' has " + n + " 'ref' parameters and might be hard to understand."
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
* external/cwe/cwe-390
|
||||
* external/cwe/cwe-391
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from CatchClause cc
|
||||
where cc.getBlock().isEmpty()
|
||||
and not exists(CommentBlock cb | cb.getParent()=cc.getBlock())
|
||||
where
|
||||
cc.getBlock().isEmpty() and
|
||||
not exists(CommentBlock cb | cb.getParent() = cc.getBlock())
|
||||
select cc, "Poor error handling: empty catch block."
|
||||
|
|
|
@ -9,31 +9,28 @@
|
|||
* correctness
|
||||
* external/cwe/cwe-486
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.ComparisonTest
|
||||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
ComparisonTest getComparisonTest(Expr e) {
|
||||
result.getExpr() = e
|
||||
}
|
||||
ComparisonTest getComparisonTest(Expr e) { result.getExpr() = e }
|
||||
|
||||
class StringComparison extends Expr {
|
||||
StringComparison() {
|
||||
exists(ComparisonTest ct |
|
||||
ct = getComparisonTest(this) |
|
||||
exists(ComparisonTest ct | ct = getComparisonTest(this) |
|
||||
ct.getComparisonKind().isEquality() and
|
||||
ct.getFirstArgument().stripCasts().getType() instanceof StringType and
|
||||
ct.getSecondArgument().stripCasts().getType() instanceof StringType
|
||||
)
|
||||
}
|
||||
|
||||
Expr getAnOperand() {
|
||||
result = getComparisonTest(this).getAnArgument()
|
||||
}
|
||||
Expr getAnOperand() { result = getComparisonTest(this).getAnArgument() }
|
||||
}
|
||||
|
||||
from StringComparison sc, PropertyAccess pa
|
||||
where sc.getAnOperand() instanceof StringLiteral
|
||||
and sc.getAnOperand() = pa
|
||||
and pa.getTarget() = any(SystemTypeClass c).getFullNameProperty()
|
||||
where
|
||||
sc.getAnOperand() instanceof StringLiteral and
|
||||
sc.getAnOperand() = pa and
|
||||
pa.getTarget() = any(SystemTypeClass c).getFullNameProperty()
|
||||
select sc, "Erroneous class compare."
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* modularity
|
||||
* external/cwe/cwe-485
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.system.Collections
|
||||
import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
|
@ -19,8 +20,7 @@ import semmle.code.csharp.frameworks.system.collections.Generic
|
|||
/** A collection interface. */
|
||||
class CollectionInterface extends Interface {
|
||||
CollectionInterface() {
|
||||
exists(Interface i |
|
||||
i = this.getABaseInterface*() |
|
||||
exists(Interface i | i = this.getABaseInterface*() |
|
||||
i instanceof SystemCollectionsICollectionInterface or
|
||||
i.getSourceDeclaration() instanceof SystemCollectionsGenericICollectionInterface or
|
||||
i instanceof SystemCollectionsIEnumerableInterface or
|
||||
|
@ -30,8 +30,10 @@ class CollectionInterface extends Interface {
|
|||
}
|
||||
|
||||
from CastExpr e, Class c, CollectionInterface i
|
||||
where e.getType() = c
|
||||
and e.getExpr().getType() = i
|
||||
and c.isImplicitlyConvertibleTo(i)
|
||||
select e, "Questionable cast from abstract '" + i.getName()
|
||||
+ "' to concrete implementation '" + c.getName() + "'."
|
||||
where
|
||||
e.getType() = c and
|
||||
e.getExpr().getType() = i and
|
||||
c.isImplicitlyConvertibleTo(i)
|
||||
select e,
|
||||
"Questionable cast from abstract '" + i.getName() + "' to concrete implementation '" + c.getName()
|
||||
+ "'."
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* @tags reliability
|
||||
* external/cwe/cwe-485
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Collections
|
||||
import DataFlow
|
||||
|
@ -31,13 +32,9 @@ predicate returnsCollection(Callable c, Field f) {
|
|||
predicate mayWriteToCollection(Expr modified) {
|
||||
modified instanceof CollectionModificationAccess
|
||||
or
|
||||
exists(Expr mid |
|
||||
mayWriteToCollection(mid) |
|
||||
localFlow(exprNode(modified), exprNode(mid))
|
||||
)
|
||||
exists(Expr mid | mayWriteToCollection(mid) | localFlow(exprNode(modified), exprNode(mid)))
|
||||
or
|
||||
exists(MethodCall mid, Callable c |
|
||||
mayWriteToCollection(mid) |
|
||||
exists(MethodCall mid, Callable c | mayWriteToCollection(mid) |
|
||||
mid.getTarget() = c and
|
||||
c.canReturn(modified)
|
||||
)
|
||||
|
@ -49,16 +46,12 @@ predicate modificationAfter(Expr before, Expr after) {
|
|||
}
|
||||
|
||||
VariableAccess varPassedInto(Callable c, Parameter p) {
|
||||
exists(Call call |
|
||||
call.getTarget() = c |
|
||||
call.getArgumentForParameter(p) = result
|
||||
)
|
||||
exists(Call call | call.getTarget() = c | call.getArgumentForParameter(p) = result)
|
||||
}
|
||||
|
||||
predicate exposesByReturn(Callable c, Field f, Expr why, string whyText) {
|
||||
returnsCollection(c, f) and
|
||||
exists(MethodCall ma |
|
||||
ma.getTarget() = c |
|
||||
exists(MethodCall ma | ma.getTarget() = c |
|
||||
mayWriteToCollection(ma) and
|
||||
why = ma and
|
||||
whyText = "after this call to " + c.getName()
|
||||
|
@ -75,8 +68,9 @@ predicate exposesByStore(Callable c, Field f, Expr why, string whyText) {
|
|||
}
|
||||
|
||||
from Callable c, Field f, Expr why, string whyText
|
||||
where exposesByReturn(c, f, why, whyText) or
|
||||
exposesByStore(c, f, why, whyText)
|
||||
select c, "'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() +
|
||||
"'. The value may be modified $@.",
|
||||
why.getLocation(), whyText
|
||||
where
|
||||
exposesByReturn(c, f, why, whyText) or
|
||||
exposesByStore(c, f, why, whyText)
|
||||
select c,
|
||||
"'" + c.getName() + "' exposes the internal representation stored in field '" + f.getName() +
|
||||
"'. The value may be modified $@.", why.getLocation(), whyText
|
||||
|
|
|
@ -10,31 +10,32 @@
|
|||
* modularity
|
||||
* external/cwe/cwe-582
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate nonEmptyArrayLiteralOrNull(Expr e) {
|
||||
e = any(ArrayCreation arr |
|
||||
exists(arr.getInitializer().getAnElement())
|
||||
or
|
||||
not arr.getALengthArgument().getValue() = "0"
|
||||
)
|
||||
exists(arr.getInitializer().getAnElement())
|
||||
or
|
||||
not arr.getALengthArgument().getValue() = "0"
|
||||
)
|
||||
or
|
||||
e instanceof NullLiteral
|
||||
or
|
||||
e = any(ConditionalExpr cond |
|
||||
nonEmptyArrayLiteralOrNull(cond.getThen()) and
|
||||
nonEmptyArrayLiteralOrNull(cond.getElse())
|
||||
)
|
||||
nonEmptyArrayLiteralOrNull(cond.getThen()) and
|
||||
nonEmptyArrayLiteralOrNull(cond.getElse())
|
||||
)
|
||||
}
|
||||
|
||||
from Field f
|
||||
where f.isPublic()
|
||||
and f.isStatic()
|
||||
and f.isReadOnly()
|
||||
and f.getType() instanceof ArrayType
|
||||
and f.fromSource()
|
||||
and forall(AssignableDefinition def |
|
||||
def.getTarget() = f |
|
||||
where
|
||||
f.isPublic() and
|
||||
f.isStatic() and
|
||||
f.isReadOnly() and
|
||||
f.getType() instanceof ArrayType and
|
||||
f.fromSource() and
|
||||
forall(AssignableDefinition def | def.getTarget() = f |
|
||||
nonEmptyArrayLiteralOrNull(def.getSource())
|
||||
)
|
||||
select f, "The array constant '" + f.getName() + "' is vulnerable to mutation."
|
||||
|
|
|
@ -10,11 +10,15 @@
|
|||
* frameworks/asp.net
|
||||
* external/cwe/cwe-489
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Util
|
||||
|
||||
from MainMethod m
|
||||
where m.fromSource()
|
||||
and exists(UsingNamespaceDirective u | u.getFile() = m.getFile()
|
||||
and u.getImportedNamespace().hasQualifiedName("System.Web"))
|
||||
where
|
||||
m.fromSource() and
|
||||
exists(UsingNamespaceDirective u |
|
||||
u.getFile() = m.getFile() and
|
||||
u.getImportedNamespace().hasQualifiedName("System.Web")
|
||||
)
|
||||
select m, "Remove debug code if your ASP.NET application is in production."
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
* @tags changeability
|
||||
* maintainability
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import MagicConstants
|
||||
|
||||
predicate selection(Element e, string msg) {
|
||||
magicConstant(e, msg)
|
||||
}
|
||||
predicate selection(Element e, string msg) { magicConstant(e, msg) }
|
||||
|
||||
from Literal e, string msg
|
||||
where selection(e, msg)
|
||||
and isNumber(e)
|
||||
and not exists(Field f | f.getInitializer() = e)
|
||||
where
|
||||
selection(e, msg) and
|
||||
isNumber(e) and
|
||||
not exists(Field f | f.getInitializer() = e)
|
||||
select e, msg
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
|
||||
import MagicConstants
|
||||
|
||||
predicate selection(Element e, string msg) {
|
||||
magicConstant(e, msg)
|
||||
}
|
||||
predicate selection(Element e, string msg) { magicConstant(e, msg) }
|
||||
|
||||
from StringLiteral e, string msg
|
||||
where selection(e, msg)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import MagicConstants
|
||||
|
||||
from Literal magicLiteral, string message, Field constant
|
||||
where isNumber(magicLiteral)
|
||||
and literalInsteadOfConstant(magicLiteral, _, message, constant)
|
||||
where
|
||||
isNumber(magicLiteral) and
|
||||
literalInsteadOfConstant(magicLiteral, _, message, constant)
|
||||
select magicLiteral, message, constant, constant.getName()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* readability
|
||||
* naming
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate typeWithConfusingName(ValueOrRefType type) {
|
||||
|
@ -16,11 +17,12 @@ predicate typeWithConfusingName(ValueOrRefType type) {
|
|||
}
|
||||
|
||||
from Method m, Method n, ValueOrRefType type
|
||||
where typeWithConfusingName(type)
|
||||
and type.fromSource()
|
||||
and m = type.getAMethod()
|
||||
and n = type.getAMethod()
|
||||
and m != n
|
||||
and m.getName().toLowerCase() = n.getName().toLowerCase()
|
||||
and m.getName() < n.getName()
|
||||
where
|
||||
typeWithConfusingName(type) and
|
||||
type.fromSource() and
|
||||
m = type.getAMethod() and
|
||||
n = type.getAMethod() and
|
||||
m != n and
|
||||
m.getName().toLowerCase() = n.getName().toLowerCase() and
|
||||
m.getName() < n.getName()
|
||||
select m, "Confusing method name, compare with $@.", n, n.getName()
|
||||
|
|
|
@ -10,15 +10,18 @@
|
|||
* readability
|
||||
* naming
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate hasSubtypeStar(RefType t, RefType u) {
|
||||
t = u
|
||||
or u.getABaseType+() = t
|
||||
t = u or
|
||||
u.getABaseType+() = t
|
||||
}
|
||||
|
||||
/** for each class, get all methods from this class or its
|
||||
superclasses, with their names in lowercase */
|
||||
/**
|
||||
* for each class, get all methods from this class or its
|
||||
* superclasses, with their names in lowercase
|
||||
*/
|
||||
predicate methodNames(RefType t, Method m, string lowercase) {
|
||||
exists(RefType t2 |
|
||||
m.getDeclaringType() = t2 and
|
||||
|
@ -28,8 +31,10 @@ predicate methodNames(RefType t, Method m, string lowercase) {
|
|||
lowercase.length() > 1
|
||||
}
|
||||
|
||||
/** For each class, find the pairs of methods that
|
||||
are candidates for being confusing in this class */
|
||||
/**
|
||||
* For each class, find the pairs of methods that
|
||||
* are candidates for being confusing in this class
|
||||
*/
|
||||
predicate confusing(Method m1, Method m2) {
|
||||
exists(RefType t, string lower |
|
||||
methodNames(t, m1, lower) and
|
||||
|
@ -38,33 +43,37 @@ predicate confusing(Method m1, Method m2) {
|
|||
)
|
||||
}
|
||||
|
||||
/* Two method names are confusing if all of the following conditions hold:
|
||||
* They are both static methods or both instance methods.
|
||||
* They are not declared in the same class, and the superclass method is
|
||||
* not overridden in an intermediate class
|
||||
* They have different names.
|
||||
* They have the same names if case is ignored.
|
||||
* There is no method in the subclass that has the same name as
|
||||
* the superclass method
|
||||
There is an additional check that only methods with names longer than one character
|
||||
can be considered confusing. */
|
||||
/*
|
||||
* Two method names are confusing if all of the following conditions hold:
|
||||
* They are both static methods or both instance methods.
|
||||
* They are not declared in the same class, and the superclass method is
|
||||
* not overridden in an intermediate class
|
||||
* They have different names.
|
||||
* They have the same names if case is ignored.
|
||||
* There is no method in the subclass that has the same name as
|
||||
* the superclass method
|
||||
* There is an additional check that only methods with names longer than one character
|
||||
* can be considered confusing.
|
||||
*/
|
||||
|
||||
from Method m1, Method m2
|
||||
where confusing(m1,m2) and
|
||||
m1.getDeclaringType() != m2.getDeclaringType() and
|
||||
(
|
||||
m1.isStatic() and m2.isStatic()
|
||||
or
|
||||
not m1.isStatic() and not m2.isStatic()
|
||||
) and
|
||||
not exists(Method mid |
|
||||
confusing(m1, mid) and
|
||||
mid.getDeclaringType().getABaseType+() = m2.getDeclaringType()
|
||||
) and
|
||||
not exists(Method notConfusing |
|
||||
notConfusing.getDeclaringType() = m1.getDeclaringType() and
|
||||
notConfusing.getName() = m2.getName()
|
||||
) and
|
||||
m1.fromSource()
|
||||
select m1, "confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and "
|
||||
+ m2.getName() + " in " + m2.getDeclaringType().getName() + "."
|
||||
where
|
||||
confusing(m1, m2) and
|
||||
m1.getDeclaringType() != m2.getDeclaringType() and
|
||||
(
|
||||
m1.isStatic() and m2.isStatic()
|
||||
or
|
||||
not m1.isStatic() and not m2.isStatic()
|
||||
) and
|
||||
not exists(Method mid |
|
||||
confusing(m1, mid) and
|
||||
mid.getDeclaringType().getABaseType+() = m2.getDeclaringType()
|
||||
) and
|
||||
not exists(Method notConfusing |
|
||||
notConfusing.getDeclaringType() = m1.getDeclaringType() and
|
||||
notConfusing.getName() = m2.getName()
|
||||
) and
|
||||
m1.fromSource()
|
||||
select m1,
|
||||
"confusing to have methods " + m1.getName() + " in " + m1.getDeclaringType().getName() + " and " +
|
||||
m2.getName() + " in " + m2.getDeclaringType().getName() + "."
|
||||
|
|
|
@ -23,13 +23,12 @@ class PublicConstantField extends Field {
|
|||
from PublicConstantField f
|
||||
where
|
||||
// The first character of the field's name is not uppercase.
|
||||
not(f.getName().charAt(0).isUppercase())
|
||||
not (f.getName().charAt(0).isUppercase())
|
||||
or
|
||||
(
|
||||
// The field's name is uppercase.
|
||||
f.getName().isUppercase()
|
||||
|
||||
f.getName().isUppercase() and
|
||||
// The field's name is at least 4 characters long.
|
||||
and f.getName().length() >= 4
|
||||
f.getName().length() >= 4
|
||||
)
|
||||
select f, "Public static read-only fields should be named in PascalCase."
|
||||
|
|
|
@ -12,51 +12,89 @@
|
|||
import csharp
|
||||
|
||||
string prefix(string typename) {
|
||||
(typename = "System.Web.UI.WebControls.Label" and result = "lbl") or
|
||||
(typename = "System.Web.UI.WebControls.TextBox" and result = "txt") or
|
||||
(typename = "System.Web.UI.WebControls.Button" and result = "btn") or
|
||||
(typename = "System.Web.UI.WebControls.LinkButton" and result = "btn") or
|
||||
(typename = "System.Web.UI.WebControls.ImageButton" and result = "ibtn") or
|
||||
(typename = "System.Web.UI.WebControls.Hyperlink" and result = "hpl") or
|
||||
(typename = "System.Web.UI.WebControls.DropDownList" and result = "cmb") or
|
||||
(typename = "System.Web.UI.WebControls.ListBox" and result = "lst") or
|
||||
(typename = "System.Web.UI.WebControls.Datagrid" and result = "dgr") or
|
||||
(typename = "System.Web.UI.WebControls.Datalist" and result = "dtl") or
|
||||
(typename = "System.Web.UI.WebControls.Repeater" and result = "rpt") or
|
||||
(typename = "System.Web.UI.WebControls.CheckBox" and result = "chk") or
|
||||
(typename = "System.Web.UI.WebControls.CheckBoxList" and result = "chklst") or
|
||||
(typename = "System.Web.UI.WebControls.RadioButtonList" and result = "radlst") or
|
||||
(typename = "System.Web.UI.WebControls.RadioButton" and result = "rad") or
|
||||
(typename = "System.Web.UI.WebControls.Image" and result = "img") or
|
||||
(typename = "System.Web.UI.WebControls.Panel" and result = "pnl") or
|
||||
(typename = "System.Web.UI.WebControls.PlaceHolder" and result = "plh") or
|
||||
(typename = "System.Web.UI.WebControls.Calendar" and result = "cal") or
|
||||
(typename = "System.Web.UI.WebControls.AdRotator" and result = "adr") or
|
||||
(typename = "System.Web.UI.WebControls.Table" and result = "tbl") or
|
||||
(typename = "System.Web.UI.WebControls.RequiredFieldValidator" and result = "rfv") or
|
||||
(typename = "System.Web.UI.WebControls.CompareValidator" and result = "cmv") or
|
||||
(typename = "System.Web.UI.WebControls.RegularExpressionValidator" and result = "rev") or
|
||||
(typename = "System.Web.UI.WebControls.CustomValidator" and result = "csv") or
|
||||
(typename = "System.Web.UI.WebControls.ValidationSummary" and result = "vsm") or
|
||||
(typename = "System.Web.UI.WebControls.XML" and result = "xml") or
|
||||
(typename = "System.Web.UI.WebControls.Literal" and result = "lit") or
|
||||
(typename = "System.Web.UI.WebControls.Form" and result = "frm") or
|
||||
(typename = "System.Web.UI.WebControls.Frame" and result = "fra") or
|
||||
(typename = "System.Web.UI.WebControls.CrystalReportViewer" and result = "crvr") or
|
||||
|
||||
(typename = "System.Web.UI.HtmlControls.TextArea" and result = "txa") or
|
||||
(typename = "System.Web.UI.HtmlControls.FileField" and result = "fle") or
|
||||
(typename = "System.Web.UI.HtmlControls.PasswordField" and result = "pwd") or
|
||||
(typename = "System.Web.UI.HtmlControls.Hidden" and result = "hdn") or
|
||||
(typename = "System.Web.UI.HtmlControls.Table" and result = "tbl") or
|
||||
(typename = "System.Web.UI.HtmlControls.FlowLayoutPanel" and result = "flp") or
|
||||
(typename = "System.Web.UI.HtmlControls.GridLayoutPanel" and result = "glp") or
|
||||
(typename = "System.Web.UI.WebControls.Label" and result = "lbl")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.TextBox" and result = "txt")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Button" and result = "btn")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.LinkButton" and result = "btn")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.ImageButton" and result = "ibtn")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Hyperlink" and result = "hpl")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.DropDownList" and result = "cmb")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.ListBox" and result = "lst")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Datagrid" and result = "dgr")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Datalist" and result = "dtl")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Repeater" and result = "rpt")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.CheckBox" and result = "chk")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.CheckBoxList" and result = "chklst")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.RadioButtonList" and result = "radlst")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.RadioButton" and result = "rad")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Image" and result = "img")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Panel" and result = "pnl")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.PlaceHolder" and result = "plh")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Calendar" and result = "cal")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.AdRotator" and result = "adr")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Table" and result = "tbl")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.RequiredFieldValidator" and result = "rfv")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.CompareValidator" and result = "cmv")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.RegularExpressionValidator" and result = "rev")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.CustomValidator" and result = "csv")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.ValidationSummary" and result = "vsm")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.XML" and result = "xml")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Literal" and result = "lit")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Form" and result = "frm")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.Frame" and result = "fra")
|
||||
or
|
||||
(typename = "System.Web.UI.WebControls.CrystalReportViewer" and result = "crvr")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.TextArea" and result = "txa")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.FileField" and result = "fle")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.PasswordField" and result = "pwd")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.Hidden" and result = "hdn")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.Table" and result = "tbl")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.FlowLayoutPanel" and result = "flp")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.GridLayoutPanel" and result = "glp")
|
||||
or
|
||||
(typename = "System.Web.UI.HtmlControls.HorizontalRule" and result = "hr")
|
||||
}
|
||||
|
||||
from Field f, RefType t, string name, string prefix
|
||||
where f.getType() = t
|
||||
and f.getName() = name
|
||||
and prefix = prefix(t.getQualifiedName())
|
||||
and not name.matches(prefix + "%")
|
||||
where
|
||||
f.getType() = t and
|
||||
f.getName() = name and
|
||||
prefix = prefix(t.getQualifiedName()) and
|
||||
not name.matches(prefix + "%")
|
||||
select f, "This field should have the prefix '" + prefix + "' to match its types."
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* @name Windows controls with generated names
|
||||
* @description Replacing the generated names in windows forms with meaningful names
|
||||
makes it easier for other developers to understand the code.
|
||||
* makes it easier for other developers to understand the code.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @precision medium
|
||||
|
@ -9,10 +9,10 @@
|
|||
* @tags readability
|
||||
* naming
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate controlName(string prefix)
|
||||
{
|
||||
predicate controlName(string prefix) {
|
||||
prefix = "[Ll]abel" or
|
||||
prefix = "[Bb]utton" or
|
||||
prefix = "[Pp]anel" or
|
||||
|
@ -28,13 +28,15 @@ predicate controlName(string prefix)
|
|||
predicate usedInHumanWrittenCode(Field f) {
|
||||
exists(File file |
|
||||
f.getAnAccess().getFile() = file and
|
||||
not file.getBaseName().toLowerCase().matches("%.designer.cs"))
|
||||
not file.getBaseName().toLowerCase().matches("%.designer.cs")
|
||||
)
|
||||
}
|
||||
|
||||
from Field field, ValueOrRefType widget, string prefix
|
||||
where widget.getABaseType*().hasQualifiedName("System.Windows.Forms.Control")
|
||||
and field.getType() = widget
|
||||
and field.getName().regexpMatch(prefix + "[0-9]+")
|
||||
and controlName(prefix)
|
||||
and usedInHumanWrittenCode(field)
|
||||
where
|
||||
widget.getABaseType*().hasQualifiedName("System.Windows.Forms.Control") and
|
||||
field.getType() = widget and
|
||||
field.getName().regexpMatch(prefix + "[0-9]+") and
|
||||
controlName(prefix) and
|
||||
usedInHumanWrittenCode(field)
|
||||
select field, "Control '" + field.getName() + "' should have a meaningful name."
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
* readability
|
||||
* naming
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
class VisibleInstanceField extends Field {
|
||||
|
@ -20,14 +21,16 @@ class VisibleInstanceField extends Field {
|
|||
}
|
||||
}
|
||||
|
||||
from RefType type, RefType supertype,
|
||||
VisibleInstanceField masked, VisibleInstanceField masking
|
||||
where type.getABaseType+() =supertype and
|
||||
masking.getDeclaringType() = type and
|
||||
masked.getDeclaringType() = supertype and
|
||||
masked.getName() = masking.getName() and
|
||||
// exclude intentional masking
|
||||
not exists(FieldAccess va | va.getTarget() = masked and
|
||||
va.getQualifier() instanceof BaseAccess) and
|
||||
type.fromSource()
|
||||
from RefType type, RefType supertype, VisibleInstanceField masked, VisibleInstanceField masking
|
||||
where
|
||||
type.getABaseType+() = supertype and
|
||||
masking.getDeclaringType() = type and
|
||||
masked.getDeclaringType() = supertype and
|
||||
masked.getName() = masking.getName() and
|
||||
// exclude intentional masking
|
||||
not exists(FieldAccess va |
|
||||
va.getTarget() = masked and
|
||||
va.getQualifier() instanceof BaseAccess
|
||||
) and
|
||||
type.fromSource()
|
||||
select masking, "This field shadows another field in a superclass."
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
* readability
|
||||
* naming
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from RefType sub, RefType sup
|
||||
where sub.getABaseType() = sup and
|
||||
sub.getName() = sup.getName() and
|
||||
sub.fromSource()
|
||||
where
|
||||
sub.getABaseType() = sup and
|
||||
sub.getName() = sup.getName() and
|
||||
sub.fromSource()
|
||||
select sub, "Class has the same name as its base class."
|
||||
|
|
|
@ -10,50 +10,56 @@
|
|||
|
||||
import csharp
|
||||
|
||||
predicate sourceFile(File f)
|
||||
{
|
||||
predicate sourceFile(File f) {
|
||||
f.fromSource() and
|
||||
not f.getAbsolutePath() = "null" and
|
||||
not f.getAbsolutePath().matches("%ActivXTabControl%.cs")
|
||||
}
|
||||
|
||||
from Variable variable, string name
|
||||
where name = variable.getName()
|
||||
and variable.fromSource()
|
||||
and sourceFile(variable.getFile())
|
||||
and not allowedName(name)
|
||||
and not allowedVariable(variable)
|
||||
//
|
||||
// Adjustable parameter:
|
||||
//
|
||||
and name.length() < 3
|
||||
where
|
||||
name = variable.getName() and
|
||||
variable.fromSource() and
|
||||
sourceFile(variable.getFile()) and
|
||||
not allowedName(name) and
|
||||
not allowedVariable(variable) and
|
||||
//
|
||||
// Adjustable parameter:
|
||||
//
|
||||
name.length() < 3
|
||||
//
|
||||
select variable, "Variable name '" + name + "' is too short."
|
||||
|
||||
//
|
||||
// Adjustable: acceptable short names
|
||||
//
|
||||
predicate allowedName(string name)
|
||||
{
|
||||
name = "url" or name = "cmd" or name = "UK" or name = "uri" or
|
||||
name = "top" or name = "row" or name = "pin" or name = "log" or
|
||||
name = "key" or name = "_"
|
||||
predicate allowedName(string name) {
|
||||
name = "url" or
|
||||
name = "cmd" or
|
||||
name = "UK" or
|
||||
name = "uri" or
|
||||
name = "top" or
|
||||
name = "row" or
|
||||
name = "pin" or
|
||||
name = "log" or
|
||||
name = "key" or
|
||||
name = "_"
|
||||
}
|
||||
|
||||
//
|
||||
// Adjustable: variables that are allowed to have short names
|
||||
//
|
||||
predicate allowedVariable(Variable variable)
|
||||
{
|
||||
exists(Parameter param | variable = param and
|
||||
predicate allowedVariable(Variable variable) {
|
||||
exists(Parameter param |
|
||||
variable = param and
|
||||
not exists(param.getAnAccess()) and
|
||||
param.getType().getName().matches("%EventArgs"))
|
||||
or
|
||||
exists(LocalVariable local | variable = local and
|
||||
local.getVariableDeclExpr().getParent() instanceof CatchClause)
|
||||
or
|
||||
exists(Call c, LambdaExpr le |
|
||||
le.getAParameter() = variable |
|
||||
c.getAnArgument() = le
|
||||
param.getType().getName().matches("%EventArgs")
|
||||
)
|
||||
or
|
||||
exists(LocalVariable local |
|
||||
variable = local and
|
||||
local.getVariableDeclExpr().getParent() instanceof CatchClause
|
||||
)
|
||||
or
|
||||
exists(Call c, LambdaExpr le | le.getAParameter() = variable | c.getAnArgument() = le)
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import csharp
|
||||
|
||||
from Class c, Method m
|
||||
where m.isExtern()
|
||||
and m.getDeclaringType() = c
|
||||
where
|
||||
m.isExtern() and
|
||||
m.getDeclaringType() = c
|
||||
select m, "Minimise the use of unmanaged code."
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
* frameworks/asp.net
|
||||
* external/cwe/cwe-472
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from ObjectCreation oc
|
||||
|
|
|
@ -7,17 +7,22 @@
|
|||
* @id cs/console-output
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Util
|
||||
|
||||
predicate isConsoleOutRedefinedSomewhere() {
|
||||
exists(MethodCall mc | mc.getTarget().hasName("SetOut") and
|
||||
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console"))
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().hasName("SetOut") and
|
||||
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")
|
||||
)
|
||||
}
|
||||
|
||||
predicate isConsoleErrorRedefinedSomewhere() {
|
||||
exists(MethodCall mc | mc.getTarget().hasName("SetError") and
|
||||
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console"))
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget().hasName("SetError") and
|
||||
mc.getTarget().getDeclaringType().hasQualifiedName("System.Console")
|
||||
)
|
||||
}
|
||||
|
||||
predicate isCallToConsoleWrite(MethodCall mc) {
|
||||
|
@ -36,8 +41,13 @@ predicate isAccessToConsoleError(PropertyAccess pa) {
|
|||
}
|
||||
|
||||
from Expr e
|
||||
where (isCallToConsoleWrite(e) and not isConsoleOutRedefinedSomewhere()
|
||||
or isAccessToConsoleOut(e) and not isConsoleOutRedefinedSomewhere()
|
||||
or isAccessToConsoleError(e) and not isConsoleErrorRedefinedSomewhere())
|
||||
and not e.getEnclosingCallable() instanceof MainMethod
|
||||
where
|
||||
(
|
||||
isCallToConsoleWrite(e) and not isConsoleOutRedefinedSomewhere()
|
||||
or
|
||||
isAccessToConsoleOut(e) and not isConsoleOutRedefinedSomewhere()
|
||||
or
|
||||
isAccessToConsoleError(e) and not isConsoleErrorRedefinedSomewhere()
|
||||
) and
|
||||
not e.getEnclosingCallable() instanceof MainMethod
|
||||
select e, "Poor logging: use of system output stream."
|
||||
|
|
|
@ -10,41 +10,38 @@
|
|||
* maintainability
|
||||
* modularity
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate virtualCallToSelfInConstructor(Expr e) {
|
||||
exists(RefType t, Virtualizable d, Callable c |
|
||||
c = e.getEnclosingCallable()
|
||||
and
|
||||
(c instanceof Constructor or c instanceof Destructor)
|
||||
and
|
||||
t = c.getDeclaringType()
|
||||
and
|
||||
virtualAccessWithThisQualifier(e, d)
|
||||
and
|
||||
t.getABaseType*() = d.getDeclaringType()
|
||||
and
|
||||
not t.isSealed()
|
||||
and
|
||||
c = e.getEnclosingCallable() and
|
||||
(c instanceof Constructor or c instanceof Destructor) and
|
||||
t = c.getDeclaringType() and
|
||||
virtualAccessWithThisQualifier(e, d) and
|
||||
t.getABaseType*() = d.getDeclaringType() and
|
||||
not t.isSealed() and
|
||||
not overriddenSealed(t.getABaseType*(), d)
|
||||
)
|
||||
}
|
||||
|
||||
predicate overriddenSealed(RefType t, Virtualizable d) {
|
||||
exists(Virtualizable od |
|
||||
od.getDeclaringType() = t
|
||||
and
|
||||
(od.getOverridee() = d or od.getImplementee() = d)
|
||||
and
|
||||
od.getDeclaringType() = t and
|
||||
(od.getOverridee() = d or od.getImplementee() = d) and
|
||||
not od.isOverridableOrImplementable()
|
||||
)
|
||||
}
|
||||
|
||||
predicate virtualAccessWithThisQualifier(Expr e, Member d) {
|
||||
exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier()) or
|
||||
exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or
|
||||
exists(VirtualPropertyAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or
|
||||
exists(VirtualIndexerAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or
|
||||
exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier())
|
||||
or
|
||||
exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier())
|
||||
or
|
||||
exists(VirtualPropertyAccess c | c = e and c.getTarget() = d and c.hasThisQualifier())
|
||||
or
|
||||
exists(VirtualIndexerAccess c | c = e and c.getTarget() = d and c.hasThisQualifier())
|
||||
or
|
||||
exists(VirtualEventAccess c | c = e and c.getTarget() = d and c.hasThisQualifier())
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,7 @@ import semmle.code.csharp.commons.ComparisonTest
|
|||
import semmle.code.csharp.commons.Constants
|
||||
|
||||
predicate isBoxingTestCase(StaticEqualsCallComparisonTest ct) {
|
||||
ct.isReferenceEquals()
|
||||
and
|
||||
ct.isReferenceEquals() and
|
||||
exists(TypeParameter tp |
|
||||
tp = ct.getFirstArgument().stripCasts().getType() and
|
||||
not tp.isValueType() and
|
||||
|
@ -25,8 +24,7 @@ predicate isBoxingTestCase(StaticEqualsCallComparisonTest ct) {
|
|||
)
|
||||
}
|
||||
|
||||
predicate isMutatingOperation(Expr e)
|
||||
{
|
||||
predicate isMutatingOperation(Expr e) {
|
||||
e.(MethodCall).getTarget().hasName("Pop")
|
||||
or
|
||||
e.(MethodCall).getTarget().hasName("Push")
|
||||
|
@ -35,16 +33,19 @@ predicate isMutatingOperation(Expr e)
|
|||
}
|
||||
|
||||
from ComparisonTest ct, Expr e, string msg
|
||||
where comparesIdenticalValues(ct)
|
||||
and e = ct.getExpr()
|
||||
and not isBoxingTestCase(ct)
|
||||
and (
|
||||
exists(string m | comparesIdenticalValuesNan(ct, m) | msg = "Comparison is equivalent to using " + m)
|
||||
where
|
||||
comparesIdenticalValues(ct) and
|
||||
e = ct.getExpr() and
|
||||
not isBoxingTestCase(ct) and
|
||||
(
|
||||
exists(string m | comparesIdenticalValuesNan(ct, m) |
|
||||
msg = "Comparison is equivalent to using " + m
|
||||
)
|
||||
or
|
||||
not comparesIdenticalValuesNan(ct, _) and msg = "Comparison of identical values."
|
||||
)
|
||||
and not isMutatingOperation(ct.getAnArgument().getAChild*())
|
||||
and not isConstantCondition(e, _) // Avoid overlap with cs/constant-condition
|
||||
and not isConstantComparison(e, _) // Avoid overlap with cs/constant-comparison
|
||||
and not isExprInAssertion(e)
|
||||
) and
|
||||
not isMutatingOperation(ct.getAnArgument().getAChild*()) and
|
||||
not isConstantCondition(e, _) and // Avoid overlap with cs/constant-condition
|
||||
not isConstantComparison(e, _) and // Avoid overlap with cs/constant-comparison
|
||||
not isExprInAssertion(e)
|
||||
select ct, msg
|
||||
|
|
|
@ -16,6 +16,7 @@ import csharp
|
|||
import semmle.code.csharp.dataflow.Nullness
|
||||
import PathGraph
|
||||
|
||||
from Dereference d, PathNode source, PathNode sink, Ssa::SourceVariable v, string msg, Element reason
|
||||
from
|
||||
Dereference d, PathNode source, PathNode sink, Ssa::SourceVariable v, string msg, Element reason
|
||||
where d.isFirstMaybeNull(v.getAnSsaDefinition(), source, sink, msg, reason)
|
||||
select d, source, sink, "Variable $@ may be null here " + msg + ".", v, v.toString(), reason, "this"
|
||||
|
|
|
@ -11,14 +11,17 @@
|
|||
* testability
|
||||
* complexity
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
class ComplexStmt extends Stmt {
|
||||
ComplexStmt() {
|
||||
(this instanceof ForStmt or
|
||||
this instanceof WhileStmt or
|
||||
this instanceof DoStmt or
|
||||
this instanceof SwitchStmt)
|
||||
(
|
||||
this instanceof ForStmt or
|
||||
this instanceof WhileStmt or
|
||||
this instanceof DoStmt or
|
||||
this instanceof SwitchStmt
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* @tags testability
|
||||
* readability
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate nontrivialLogicalOperator(BinaryLogicalOperation e) {
|
||||
|
@ -17,13 +18,13 @@ predicate nontrivialLogicalOperator(BinaryLogicalOperation e) {
|
|||
)
|
||||
}
|
||||
|
||||
predicate logicalParent(LogicalOperation op, LogicalOperation parent)
|
||||
{
|
||||
parent = op.getParent()
|
||||
}
|
||||
predicate logicalParent(LogicalOperation op, LogicalOperation parent) { parent = op.getParent() }
|
||||
|
||||
from Expr e, int operators
|
||||
where not (e.getParent() instanceof LogicalOperation)
|
||||
and operators = count(BinaryLogicalOperation op | logicalParent*(op, e) and nontrivialLogicalOperator(op))
|
||||
and operators > 3
|
||||
where
|
||||
not (e.getParent() instanceof LogicalOperation) and
|
||||
operators = count(BinaryLogicalOperation op |
|
||||
logicalParent*(op, e) and nontrivialLogicalOperator(op)
|
||||
) and
|
||||
operators > 3
|
||||
select e.getLocation(), "Complex condition: too many logical operations in this expression."
|
||||
|
|
|
@ -21,8 +21,10 @@ predicate lockedFieldUpdate(LockStmt lock, Field f, AssignableDefinition def) {
|
|||
}
|
||||
|
||||
from LockStmt lock, Expr e, Field f, AssignableDefinition def
|
||||
where e = lock.getExpr()
|
||||
and f.getAnAccess() = e
|
||||
and lockedFieldUpdate(lock, f, def)
|
||||
select e, "Locking field $@ guards the initial value, not the value which may be seen from another thread after $@.",
|
||||
where
|
||||
e = lock.getExpr() and
|
||||
f.getAnAccess() = e and
|
||||
lockedFieldUpdate(lock, f, def)
|
||||
select e,
|
||||
"Locking field $@ guards the initial value, not the value which may be seen from another thread after $@.",
|
||||
f, f.getName(), def, "reassignment"
|
||||
|
|
|
@ -38,7 +38,8 @@ LockStmt getAReachableLockStmt(Callable callable) {
|
|||
predicate nestedLocks(Variable outerVariable, Variable innerVariable, LockStmt outer, LockStmt inner) {
|
||||
outerVariable = outer.getLockVariable() and
|
||||
innerVariable = inner.getLockVariable() and
|
||||
outerVariable != innerVariable and (
|
||||
outerVariable != innerVariable and
|
||||
(
|
||||
inner = outer.getALockedStmt()
|
||||
or
|
||||
exists(Call call | call.getEnclosingStmt() = outer.getALockedStmt() |
|
||||
|
@ -54,9 +55,6 @@ where
|
|||
nestedLocks(v1, v2, outer1, inner1) and
|
||||
nestedLocks(v2, v1, outer2, inner2) and
|
||||
v1.getName() <= v2.getName()
|
||||
select v1, "Inconsistent lock sequence with $@. Lock sequences $@, $@ and $@, $@ found.",
|
||||
v2, v2.getName(),
|
||||
outer1, v1.getName(),
|
||||
inner1, v2.getName(),
|
||||
outer2, v2.getName(),
|
||||
inner2, v1.getName()
|
||||
select v1, "Inconsistent lock sequence with $@. Lock sequences $@, $@ and $@, $@ found.", v2,
|
||||
v2.getName(), outer1, v1.getName(), inner1, v2.getName(), outer2, v2.getName(), inner2,
|
||||
v1.getName()
|
||||
|
|
|
@ -15,5 +15,5 @@
|
|||
import csharp
|
||||
|
||||
from LockStmt s, ThisAccess a
|
||||
where a=s.getExpr()
|
||||
where a = s.getExpr()
|
||||
select a, "'this' used in lock statement."
|
||||
|
|
|
@ -16,10 +16,19 @@ import csharp
|
|||
import Concurrency
|
||||
|
||||
from LockedBlock l, WaitStmt w, string lockedItem
|
||||
where l.getALockedStmt()=w and
|
||||
where
|
||||
l.getALockedStmt() = w and
|
||||
(
|
||||
exists( Variable v | v=l.getLockVariable() and not v=w.getWaitVariable() and lockedItem=v.getName() ) or
|
||||
exists( Type t | t=l.getLockTypeObject() and not t=w.getWaitTypeObject() and lockedItem = "typeof("+t.getName()+")" ) or
|
||||
( l.isLockThis() and not w.isWaitThis() and lockedItem="this" )
|
||||
exists(Variable v |
|
||||
v = l.getLockVariable() and not v = w.getWaitVariable() and lockedItem = v.getName()
|
||||
)
|
||||
or
|
||||
exists(Type t |
|
||||
t = l.getLockTypeObject() and
|
||||
not t = w.getWaitTypeObject() and
|
||||
lockedItem = "typeof(" + t.getName() + ")"
|
||||
)
|
||||
or
|
||||
(l.isLockThis() and not w.isWaitThis() and lockedItem = "this")
|
||||
)
|
||||
select w, "'" + lockedItem + "' is locked during this wait."
|
||||
|
|
|
@ -15,26 +15,17 @@ import csharp
|
|||
|
||||
from Property p, Field f
|
||||
where
|
||||
f.getDeclaringType() = p.getDeclaringType()
|
||||
and
|
||||
f.getDeclaringType() = p.getDeclaringType() and
|
||||
exists(Setter setter, LockStmt writelock, FieldWrite writeaccess |
|
||||
p.getSetter() = setter
|
||||
and
|
||||
writeaccess = f.getAnAccess()
|
||||
and
|
||||
writelock.getEnclosingCallable() = setter
|
||||
and
|
||||
p.getSetter() = setter and
|
||||
writeaccess = f.getAnAccess() and
|
||||
writelock.getEnclosingCallable() = setter and
|
||||
writelock.getAChildStmt+().getAChildExpr+() = writeaccess
|
||||
)
|
||||
and
|
||||
) and
|
||||
exists(Getter getter, FieldRead readaccess |
|
||||
getter = p.getGetter()
|
||||
and
|
||||
readaccess = f.getAnAccess()
|
||||
and
|
||||
readaccess.getEnclosingCallable() = getter
|
||||
and
|
||||
not exists(LockStmt readlock |
|
||||
readlock.getAChildStmt+().getAChildExpr+() = readaccess)
|
||||
)
|
||||
getter = p.getGetter() and
|
||||
readaccess = f.getAnAccess() and
|
||||
readaccess.getEnclosingCallable() = getter and
|
||||
not exists(LockStmt readlock | readlock.getAChildStmt+().getAChildExpr+() = readaccess)
|
||||
)
|
||||
select p, "Field '$@' is guarded by a lock in the setter but not in the getter.", f, f.getName()
|
||||
|
|
|
@ -15,7 +15,7 @@ import csharp
|
|||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class DoubleCheckedLock extends StructuralComparisonConfiguration {
|
||||
DoubleCheckedLock() { this="double checked lock" }
|
||||
DoubleCheckedLock() { this = "double checked lock" }
|
||||
|
||||
override predicate candidate(Element x, Element y) {
|
||||
exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock |
|
||||
|
@ -28,8 +28,7 @@ class DoubleCheckedLock extends StructuralComparisonConfiguration {
|
|||
}
|
||||
|
||||
predicate doubleCheckedLock(Field field, IfStmt ifs) {
|
||||
exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 |
|
||||
ifs.getCondition() = eq1 |
|
||||
exists(DoubleCheckedLock config, LockStmt lock, Expr eq1, Expr eq2 | ifs.getCondition() = eq1 |
|
||||
lock = ifs.getThen().stripSingletonBlocks() and
|
||||
config.same(eq1, eq2) and
|
||||
field.getAnAccess() = eq1.getAChildExpr*()
|
||||
|
@ -37,9 +36,7 @@ predicate doubleCheckedLock(Field field, IfStmt ifs) {
|
|||
}
|
||||
|
||||
from Field field, IfStmt ifs
|
||||
where doubleCheckedLock(field, ifs)
|
||||
and not field.isVolatile()
|
||||
select ifs, "Field $@ should be 'volatile' for this double-checked lock.",
|
||||
field, field.getName()
|
||||
|
||||
|
||||
where
|
||||
doubleCheckedLock(field, ifs) and
|
||||
not field.isVolatile()
|
||||
select ifs, "Field $@ should be 'volatile' for this double-checked lock.", field, field.getName()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
* external/cwe/cwe-362
|
||||
* external/cwe/cwe-567
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DataMembers
|
||||
import ThreadCreation
|
||||
|
@ -24,7 +25,8 @@ predicate correctlySynchronized(CollectionMember c, Expr access) {
|
|||
}
|
||||
|
||||
ControlFlow::Node unlockedReachable(Callable a) {
|
||||
result = a.getEntryPoint() or
|
||||
result = a.getEntryPoint()
|
||||
or
|
||||
exists(ControlFlow::Node mid | mid = unlockedReachable(a) |
|
||||
not mid.getElement() instanceof LockingCall and
|
||||
result = mid.getASuccessor()
|
||||
|
@ -40,22 +42,22 @@ predicate unlockedCalls(Callable a, Callable b) {
|
|||
}
|
||||
|
||||
predicate writtenStaticDictionary(CollectionMember c) {
|
||||
c.getType().(ValueOrRefType).getABaseType*().hasName("IDictionary")
|
||||
and c.isStatic()
|
||||
and exists(Expr write | write = c.getAWrite() |
|
||||
c.getType().(ValueOrRefType).getABaseType*().hasName("IDictionary") and
|
||||
c.isStatic() and
|
||||
exists(Expr write | write = c.getAWrite() |
|
||||
not write.getEnclosingCallable() instanceof StaticConstructor
|
||||
)
|
||||
}
|
||||
|
||||
predicate nonStaticCallable(Callable c) {
|
||||
not c.(Modifiable).isStatic()
|
||||
}
|
||||
predicate nonStaticCallable(Callable c) { not c.(Modifiable).isStatic() }
|
||||
|
||||
from CollectionMember c, Expr a, ConcurrentEntryPoint e,Callable enclosing
|
||||
where a = c.getAReadOrWrite()
|
||||
and enclosing = a.getEnclosingCallable()
|
||||
and nonStaticCallable(enclosing)
|
||||
and not correctlySynchronized(c, a)
|
||||
and unlockedCalls*(e, enclosing)
|
||||
and writtenStaticDictionary(c)
|
||||
select a, "Unsynchronized access to $@ in non-static context from $@.", c, c.getName(), e, e.getName()
|
||||
from CollectionMember c, Expr a, ConcurrentEntryPoint e, Callable enclosing
|
||||
where
|
||||
a = c.getAReadOrWrite() and
|
||||
enclosing = a.getEnclosingCallable() and
|
||||
nonStaticCallable(enclosing) and
|
||||
not correctlySynchronized(c, a) and
|
||||
unlockedCalls*(e, enclosing) and
|
||||
writtenStaticDictionary(c)
|
||||
select a, "Unsynchronized access to $@ in non-static context from $@.", c, c.getName(), e,
|
||||
e.getName()
|
||||
|
|
|
@ -9,10 +9,14 @@
|
|||
* external/cwe/cwe-258
|
||||
* external/cwe/cwe-862
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from XMLAttribute a
|
||||
where a.getName().toLowerCase() = "password" and a.getValue() = ""
|
||||
or a.getName().toLowerCase() = "pwd" and a.getValue() = ""
|
||||
or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=\\s*;.*")
|
||||
where
|
||||
a.getName().toLowerCase() = "password" and a.getValue() = ""
|
||||
or
|
||||
a.getName().toLowerCase() = "pwd" and a.getValue() = ""
|
||||
or
|
||||
a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=\\s*;.*")
|
||||
select a, "Do not use empty passwords."
|
||||
|
|
|
@ -10,10 +10,14 @@
|
|||
* external/cwe/cwe-256
|
||||
* external/cwe/cwe-313
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from XMLAttribute a
|
||||
where a.getName().toLowerCase() = "password" and not a.getValue() = ""
|
||||
or a.getName().toLowerCase() = "pwd" and not a.getValue() = ""
|
||||
or a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*")
|
||||
where
|
||||
a.getName().toLowerCase() = "password" and not a.getValue() = ""
|
||||
or
|
||||
a.getName().toLowerCase() = "pwd" and not a.getValue() = ""
|
||||
or
|
||||
a.getValue().regexpMatch("(?is).*(pwd|password)\\s*=(?!\\s*;).*")
|
||||
select a, "Avoid plaintext passwords in configuration files."
|
||||
|
|
|
@ -9,45 +9,43 @@
|
|||
* useless-code
|
||||
* external/cwe/cwe-561
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Util
|
||||
import semmle.code.csharp.frameworks.Test
|
||||
import semmle.code.csharp.metrics.Coupling
|
||||
|
||||
predicate potentiallyUsedFromXaml(RefType t)
|
||||
{
|
||||
predicate potentiallyUsedFromXaml(RefType t) {
|
||||
exists(string name | name = t.getABaseType*().getQualifiedName() |
|
||||
name = "System.Windows.Data.IValueConverter"
|
||||
or name = "System.Windows.Data.IMultiValueConverter"
|
||||
name = "System.Windows.Data.IValueConverter" or
|
||||
name = "System.Windows.Data.IMultiValueConverter"
|
||||
)
|
||||
}
|
||||
|
||||
class ExportAttribute extends Attribute
|
||||
{
|
||||
ExportAttribute()
|
||||
{
|
||||
class ExportAttribute extends Attribute {
|
||||
ExportAttribute() {
|
||||
getType().hasQualifiedName("System.ComponentModel.Composition.ExportAttribute")
|
||||
}
|
||||
}
|
||||
|
||||
from RefType t
|
||||
where
|
||||
not extractionIsStandalone()
|
||||
and t.fromSource()
|
||||
and t = t.getSourceDeclaration()
|
||||
and not t instanceof AnonymousClass
|
||||
and not (t.isPublic() or t.isProtected())
|
||||
and not exists (ValueOrRefType dependent | depends(dependent, t) and dependent != t)
|
||||
and not exists (ConstructedType ct | usesType(ct, t))
|
||||
and not exists (MethodCall call | usesType(call.getTarget().(ConstructedMethod).getATypeArgument(), t))
|
||||
and not t.getAMethod() instanceof MainMethod
|
||||
and not potentiallyUsedFromXaml(t)
|
||||
and not exists(TypeofExpr typeof | typeof.getTypeAccess().getTarget() = t)
|
||||
and not t instanceof TestClass
|
||||
not extractionIsStandalone() and
|
||||
t.fromSource() and
|
||||
t = t.getSourceDeclaration() and
|
||||
not t instanceof AnonymousClass and
|
||||
not (t.isPublic() or t.isProtected()) and
|
||||
not exists(ValueOrRefType dependent | depends(dependent, t) and dependent != t) and
|
||||
not exists(ConstructedType ct | usesType(ct, t)) and
|
||||
not exists(MethodCall call | usesType(call.getTarget().(ConstructedMethod).getATypeArgument(), t)) and
|
||||
not t.getAMethod() instanceof MainMethod and
|
||||
not potentiallyUsedFromXaml(t) and
|
||||
not exists(TypeofExpr typeof | typeof.getTypeAccess().getTarget() = t) and
|
||||
not t instanceof TestClass and
|
||||
// MemberConstant nodes are compile-time constant and can appear in various contexts
|
||||
// where they don't have enclosing callables or types (e.g. in attribute values).
|
||||
// Classes that are declared purely to hold member constants which are used are,
|
||||
// therefore, not dead.
|
||||
and not exists(t.getAMember().(MemberConstant).getAnAccess())
|
||||
and not t.getAnAttribute() instanceof ExportAttribute
|
||||
not exists(t.getAMember().(MemberConstant).getAnAccess()) and
|
||||
not t.getAnAttribute() instanceof ExportAttribute
|
||||
select t, "Unused reference type " + t + "."
|
||||
|
|
|
@ -20,8 +20,7 @@ import csharp
|
|||
Callable getACapturingCallableAncestor(LocalVariable v) {
|
||||
result = v.getACapturingCallable()
|
||||
or
|
||||
exists(Callable mid |
|
||||
mid = getACapturingCallableAncestor(v) |
|
||||
exists(Callable mid | mid = getACapturingCallableAncestor(v) |
|
||||
result = mid.getEnclosingCallable() and
|
||||
not v.getEnclosingCallable() = result
|
||||
)
|
||||
|
@ -37,8 +36,7 @@ Expr getADelegateExpr(Callable c) {
|
|||
* Holds if `c` is a call where any delegate argument is evaluated immediately.
|
||||
*/
|
||||
predicate nonEscapingCall(Call c) {
|
||||
exists(string name |
|
||||
c.getTarget().hasName(name) |
|
||||
exists(string name | c.getTarget().hasName(name) |
|
||||
name = "ForEach" or
|
||||
name = "Count" or
|
||||
name = "Any" or
|
||||
|
@ -62,8 +60,7 @@ predicate nonEscapingCall(Call c) {
|
|||
* `v` may escape the local scope.
|
||||
*/
|
||||
predicate mayEscape(LocalVariable v) {
|
||||
exists(Callable c, Expr e, Expr succ |
|
||||
c = getACapturingCallableAncestor(v) |
|
||||
exists(Callable c, Expr e, Expr succ | c = getACapturingCallableAncestor(v) |
|
||||
e = getADelegateExpr(c) and
|
||||
DataFlow::localFlow(DataFlow::exprNode(e), DataFlow::exprNode(succ)) and
|
||||
not succ = any(DelegateCall dc).getDelegateExpr() and
|
||||
|
@ -80,15 +77,15 @@ class RelevantDefinition extends AssignableDefinition {
|
|||
this instanceof AssignableDefinitions::MutationDefinition
|
||||
or
|
||||
this instanceof AssignableDefinitions::TupleAssignmentDefinition
|
||||
or
|
||||
// Discards in out assignments are only possible from C# 7 (2017), so we disable this case
|
||||
// for now
|
||||
//or
|
||||
//this.(AssignableDefinitions::OutRefDefinition).getTargetAccess().isOutArgument()
|
||||
or
|
||||
this.(AssignableDefinitions::LocalVariableDefinition).getDeclaration() = any(LocalVariableDeclExpr lvde |
|
||||
lvde = any(SpecificCatchClause scc).getVariableDeclExpr() or
|
||||
lvde = any(ForeachStmt fs).getVariableDeclExpr()
|
||||
)
|
||||
lvde = any(SpecificCatchClause scc).getVariableDeclExpr() or
|
||||
lvde = any(ForeachStmt fs).getVariableDeclExpr()
|
||||
)
|
||||
or
|
||||
this instanceof AssignableDefinitions::IsPatternDefinition
|
||||
or
|
||||
|
@ -97,8 +94,7 @@ class RelevantDefinition extends AssignableDefinition {
|
|||
|
||||
/** Holds if this assignment may be live. */
|
||||
private predicate isMaybeLive() {
|
||||
exists(LocalVariable v |
|
||||
v = this.getTarget() |
|
||||
exists(LocalVariable v | v = this.getTarget() |
|
||||
// SSA definitions are only created for live variables
|
||||
this = any(Ssa::ExplicitDefinition ssaDef).getADefinition()
|
||||
or
|
||||
|
@ -117,10 +113,8 @@ class RelevantDefinition extends AssignableDefinition {
|
|||
*/
|
||||
private predicate isDefaultLikeInitializer() {
|
||||
this.isInitializer() and
|
||||
exists(Expr e |
|
||||
e = this.getSource() |
|
||||
exists(string val |
|
||||
val = e.getValue() |
|
||||
exists(Expr e | e = this.getSource() |
|
||||
exists(string val | val = e.getValue() |
|
||||
val = "0" or
|
||||
val = "-1" or
|
||||
val = "" or
|
||||
|
@ -129,7 +123,10 @@ class RelevantDefinition extends AssignableDefinition {
|
|||
or
|
||||
e instanceof NullLiteral
|
||||
or
|
||||
e = any(Field f | f.isStatic() and (f.isReadOnly() or f.isConst())).getAnAccess()
|
||||
e = any(Field f |
|
||||
f.isStatic() and
|
||||
(f.isReadOnly() or f.isConst())
|
||||
).getAnAccess()
|
||||
or
|
||||
e instanceof DefaultValueExpr
|
||||
or
|
||||
|
@ -151,8 +148,7 @@ class RelevantDefinition extends AssignableDefinition {
|
|||
(
|
||||
not this.isDefaultLikeInitializer()
|
||||
or
|
||||
not exists(AssignableDefinition other |
|
||||
other.getTarget() = this.getTarget() |
|
||||
not exists(AssignableDefinition other | other.getTarget() = this.getTarget() |
|
||||
other != this
|
||||
)
|
||||
)
|
||||
|
@ -161,6 +157,7 @@ class RelevantDefinition extends AssignableDefinition {
|
|||
}
|
||||
|
||||
from RelevantDefinition def, LocalVariable v
|
||||
where v = def.getTarget()
|
||||
and def.isDead()
|
||||
where
|
||||
v = def.getTarget() and
|
||||
def.isDead()
|
||||
select def, "This assignment to $@ is useless, since its value is never read.", v, v.getName()
|
||||
|
|
|
@ -16,108 +16,102 @@ import semmle.code.csharp.frameworks.System
|
|||
import semmle.code.csharp.frameworks.system.runtime.InteropServices
|
||||
|
||||
// Any field transitively contained in t.
|
||||
Field getANestedField(ValueOrRefType t)
|
||||
{
|
||||
Field getANestedField(ValueOrRefType t) {
|
||||
result.getDeclaringType() = t
|
||||
or
|
||||
exists(Field mid |
|
||||
mid=getANestedField(t)
|
||||
and
|
||||
mid.getType() = result.getDeclaringType())
|
||||
mid = getANestedField(t) and
|
||||
mid.getType() = result.getDeclaringType()
|
||||
)
|
||||
}
|
||||
|
||||
// Any ValueOrRefType referenced by a Type, including TypeParameters.
|
||||
ValueOrRefType getAReferencedType(Type t)
|
||||
{
|
||||
ValueOrRefType getAReferencedType(Type t) {
|
||||
result = t
|
||||
or
|
||||
result = t.(TypeParameter).getASuppliedType()
|
||||
}
|
||||
|
||||
predicate isTypeExternallyInitialized(ValueOrRefType t)
|
||||
{
|
||||
predicate isTypeExternallyInitialized(ValueOrRefType t) {
|
||||
// The type got created via a call to PtrToStructure().
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod()
|
||||
and
|
||||
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureTypeMethod() and
|
||||
t = getAReferencedType(mc.getArgument(1).(TypeofExpr).getTypeAccess().getTarget())
|
||||
)
|
||||
|
||||
)
|
||||
or
|
||||
// The type got created via a call to PtrToStructure().
|
||||
or exists(MethodCall mc |
|
||||
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod()
|
||||
and
|
||||
exists(MethodCall mc |
|
||||
mc.getTarget() = any(SystemRuntimeInteropServicesMarshalClass c).getPtrToStructureObjectMethod() and
|
||||
t = getAReferencedType(mc.getArgument(1).getType())
|
||||
)
|
||||
|
||||
)
|
||||
or
|
||||
// An extern method exists which could initialize the type.
|
||||
or exists(Method m, Parameter p |
|
||||
exists(Method m, Parameter p |
|
||||
isExternMethod(m) and
|
||||
p=m.getAParameter() and
|
||||
p = m.getAParameter() and
|
||||
t = p.getType()
|
||||
|
|
||||
p.isOut() or p.isRef())
|
||||
|
||||
|
|
||||
p.isOut() or p.isRef()
|
||||
)
|
||||
or
|
||||
// The data structure has been cast to a pointer - all bets are off.
|
||||
or exists(CastExpr c |
|
||||
t = getAReferencedType(c.getTargetType().(PointerType).getReferentType()))
|
||||
exists(CastExpr c | t = getAReferencedType(c.getTargetType().(PointerType).getReferentType()))
|
||||
}
|
||||
|
||||
// The type is potentially marshaled using an extern or interop.
|
||||
predicate isFieldExternallyInitialized(Field f)
|
||||
{
|
||||
predicate isFieldExternallyInitialized(Field f) {
|
||||
exists(ValueOrRefType t |
|
||||
f = getANestedField(t)
|
||||
and
|
||||
isTypeExternallyInitialized(t))
|
||||
f = getANestedField(t) and
|
||||
isTypeExternallyInitialized(t)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isExternMethod(Method externMethod)
|
||||
{
|
||||
predicate isExternMethod(Method externMethod) {
|
||||
externMethod.isExtern()
|
||||
or
|
||||
externMethod.getAnAttribute().getType() instanceof SystemRuntimeInteropServicesDllImportAttributeClass
|
||||
externMethod.getAnAttribute().getType() instanceof
|
||||
SystemRuntimeInteropServicesDllImportAttributeClass
|
||||
or
|
||||
externMethod.getDeclaringType().getAnAttribute().getType() instanceof SystemRuntimeInteropServicesComImportAttributeClass
|
||||
externMethod.getDeclaringType().getAnAttribute().getType() instanceof
|
||||
SystemRuntimeInteropServicesComImportAttributeClass
|
||||
}
|
||||
|
||||
from Field f, FieldRead fa
|
||||
where
|
||||
f.fromSource()
|
||||
and not extractionIsStandalone()
|
||||
and not f.isReadOnly()
|
||||
and not f.isConst()
|
||||
and not f.getDeclaringType() instanceof Enum
|
||||
and not f.getType() instanceof Struct
|
||||
and not exists(Assignment ae, Field g |
|
||||
ae.getLValue().(FieldAccess).getTarget() = g
|
||||
and g.getSourceDeclaration() = f
|
||||
and not (ae.getRValue() instanceof NullLiteral)
|
||||
)
|
||||
and not exists(MethodCall mc, int i, Field g |
|
||||
exists(Parameter p | mc.getTarget().getParameter(i) = p |
|
||||
p.isOut() or p.isRef()
|
||||
)
|
||||
and mc.getArgument(i) = g.getAnAccess()
|
||||
and g.getSourceDeclaration() = f
|
||||
)
|
||||
and not isFieldExternallyInitialized(f)
|
||||
and not exists(f.getAnAttribute())
|
||||
and not exists(Expr init, Field g |
|
||||
f.fromSource() and
|
||||
not extractionIsStandalone() and
|
||||
not f.isReadOnly() and
|
||||
not f.isConst() and
|
||||
not f.getDeclaringType() instanceof Enum and
|
||||
not f.getType() instanceof Struct and
|
||||
not exists(Assignment ae, Field g |
|
||||
ae.getLValue().(FieldAccess).getTarget() = g and
|
||||
g.getSourceDeclaration() = f and
|
||||
not (ae.getRValue() instanceof NullLiteral)
|
||||
) and
|
||||
not exists(MethodCall mc, int i, Field g |
|
||||
exists(Parameter p | mc.getTarget().getParameter(i) = p | p.isOut() or p.isRef()) and
|
||||
mc.getArgument(i) = g.getAnAccess() and
|
||||
g.getSourceDeclaration() = f
|
||||
and g.getInitializer() = init
|
||||
and not init instanceof NullLiteral
|
||||
)
|
||||
and not exists(AssignOperation ua, Field g |
|
||||
ua.getLValue().(FieldAccess).getTarget() = g
|
||||
and g.getSourceDeclaration() = f
|
||||
)
|
||||
and not exists(MutatorOperation op |
|
||||
) and
|
||||
not isFieldExternallyInitialized(f) and
|
||||
not exists(f.getAnAttribute()) and
|
||||
not exists(Expr init, Field g |
|
||||
g.getSourceDeclaration() = f and
|
||||
g.getInitializer() = init and
|
||||
not init instanceof NullLiteral
|
||||
) and
|
||||
not exists(AssignOperation ua, Field g |
|
||||
ua.getLValue().(FieldAccess).getTarget() = g and
|
||||
g.getSourceDeclaration() = f
|
||||
) and
|
||||
not exists(MutatorOperation op |
|
||||
op.getAnOperand().(FieldAccess).getTarget().getSourceDeclaration() = f
|
||||
) and
|
||||
exists(Field g |
|
||||
fa.getTarget() = g and
|
||||
g.getSourceDeclaration() = f
|
||||
)
|
||||
and exists(Field g |
|
||||
fa.getTarget() = g
|
||||
and g.getSourceDeclaration() = f
|
||||
)
|
||||
select f, "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.",
|
||||
fa, "here"
|
||||
select f,
|
||||
"The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.", fa,
|
||||
"here"
|
||||
|
|
|
@ -9,13 +9,14 @@
|
|||
* useless-code
|
||||
* external/cwe/cwe-561
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DeadCode
|
||||
|
||||
from Field f
|
||||
where
|
||||
not extractionIsStandalone()
|
||||
and f.fromSource()
|
||||
and isDeadField(f)
|
||||
and not f.getDeclaringType().isPartial()
|
||||
not extractionIsStandalone() and
|
||||
f.fromSource() and
|
||||
isDeadField(f) and
|
||||
not f.getDeclaringType().isPartial()
|
||||
select f, "Unused field (or field used from dead method only)"
|
||||
|
|
|
@ -10,13 +10,14 @@
|
|||
* useless-code
|
||||
* external/cwe/cwe-561
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import DeadCode
|
||||
|
||||
from Method m
|
||||
where
|
||||
not extractionIsStandalone()
|
||||
and m.fromSource()
|
||||
and isDeadMethod(m)
|
||||
and not m.getDeclaringType().isPartial()
|
||||
not extractionIsStandalone() and
|
||||
m.fromSource() and
|
||||
isDeadMethod(m) and
|
||||
not m.getDeclaringType().isPartial()
|
||||
select m, "Unused method (or method called from dead method only)"
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
import Documentation
|
||||
|
||||
from SourceMethodOrConstructor m, ParamXmlComment comment, string paramName
|
||||
where comment = getADeclarationXmlComment(m)
|
||||
and comment.getName(_)=paramName
|
||||
and not m.getAParameter().getName() = paramName
|
||||
where
|
||||
comment = getADeclarationXmlComment(m) and
|
||||
comment.getName(_) = paramName and
|
||||
not m.getAParameter().getName() = paramName
|
||||
select m, "Documentation specifies an invalid parameter name $@.", comment, paramName
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
import Documentation
|
||||
|
||||
from UnboundGeneric d, TypeparamXmlComment comment, string paramName
|
||||
where comment = getADeclarationXmlComment(d)
|
||||
and comment.getName(_) = paramName
|
||||
and not d.getATypeParameter().getName() = paramName
|
||||
where
|
||||
comment = getADeclarationXmlComment(d) and
|
||||
comment.getName(_) = paramName and
|
||||
not d.getATypeParameter().getName() = paramName
|
||||
select d, "Documentation specifies an invalid type parameter name $@.", comment, paramName
|
||||
|
|
|
@ -12,16 +12,20 @@
|
|||
import Documentation
|
||||
|
||||
/** Generate a user-friendly string for the declaration */
|
||||
string declarationDescription(Declaration d)
|
||||
{
|
||||
d instanceof Class and result="class" or
|
||||
d instanceof Interface and result="interface" or
|
||||
d instanceof Method and result="method" or
|
||||
d instanceof Constructor and result="constructor" or
|
||||
d instanceof Struct and result="struct"
|
||||
string declarationDescription(Declaration d) {
|
||||
d instanceof Class and result = "class"
|
||||
or
|
||||
d instanceof Interface and result = "interface"
|
||||
or
|
||||
d instanceof Method and result = "method"
|
||||
or
|
||||
d instanceof Constructor and result = "constructor"
|
||||
or
|
||||
d instanceof Struct and result = "struct"
|
||||
}
|
||||
|
||||
from Declaration decl
|
||||
where isDocumentationNeeded(decl)
|
||||
and not declarationHasXmlComment(decl)
|
||||
where
|
||||
isDocumentationNeeded(decl) and
|
||||
not declarationHasXmlComment(decl)
|
||||
select decl, "Public " + declarationDescription(decl) + " should be documented."
|
||||
|
|
|
@ -12,15 +12,16 @@
|
|||
import Documentation
|
||||
|
||||
from SourceMethodOrConstructor m, ThrowElement throw, RefType throwType
|
||||
where declarationHasXmlComment(m)
|
||||
and m = throw.getEnclosingCallable()
|
||||
and throwType = throw.getExpr().getType()
|
||||
and not exists(ExceptionXmlComment comment, int offset, string exceptionName, RefType throwBaseType |
|
||||
comment = getADeclarationXmlComment(m)
|
||||
and exceptionName = comment.getCref(offset)
|
||||
and throwType.getABaseType*() = throwBaseType
|
||||
and (throwBaseType.hasName(exceptionName) or throwBaseType.hasQualifiedName(exceptionName))
|
||||
where
|
||||
declarationHasXmlComment(m) and
|
||||
m = throw.getEnclosingCallable() and
|
||||
throwType = throw.getExpr().getType() and
|
||||
not exists(ExceptionXmlComment comment, int offset, string exceptionName, RefType throwBaseType |
|
||||
comment = getADeclarationXmlComment(m) and
|
||||
exceptionName = comment.getCref(offset) and
|
||||
throwType.getABaseType*() = throwBaseType and
|
||||
(throwBaseType.hasName(exceptionName) or throwBaseType.hasQualifiedName(exceptionName))
|
||||
// and comment.hasBody(offset) // Too slow
|
||||
)
|
||||
and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
|
||||
) and
|
||||
not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
|
||||
select m, "Exception $@ should be documented.", throw, throw.getExpr().getType().getName()
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
import Documentation
|
||||
|
||||
from SourceMethodOrConstructor m, SourceParameter p
|
||||
where p = m.getAParameter()
|
||||
and declarationHasXmlComment(m)
|
||||
and not exists( ParamXmlComment c, int offset |
|
||||
c = getADeclarationXmlComment(m)
|
||||
and c.getName(offset) = p.getName()
|
||||
and c.hasBody(offset) )
|
||||
and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
|
||||
where
|
||||
p = m.getAParameter() and
|
||||
declarationHasXmlComment(m) and
|
||||
not exists(ParamXmlComment c, int offset |
|
||||
c = getADeclarationXmlComment(m) and
|
||||
c.getName(offset) = p.getName() and
|
||||
c.hasBody(offset)
|
||||
) and
|
||||
not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
|
||||
select p, "Parameter should be documented."
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
import Documentation
|
||||
|
||||
from SourceMethod m
|
||||
where declarationHasXmlComment(m)
|
||||
and forall(ReturnsXmlComment c | c=getADeclarationXmlComment(m) |
|
||||
forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset) ) )
|
||||
and not m.getReturnType() instanceof VoidType
|
||||
and not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
|
||||
where
|
||||
declarationHasXmlComment(m) and
|
||||
forall(ReturnsXmlComment c | c = getADeclarationXmlComment(m) |
|
||||
forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset))
|
||||
) and
|
||||
not m.getReturnType() instanceof VoidType and
|
||||
not getADeclarationXmlComment(m) instanceof InheritDocXmlComment
|
||||
select m, "Return value should be documented."
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
import Documentation
|
||||
|
||||
from Declaration decl
|
||||
where declarationHasXmlComment(decl)
|
||||
and isDocumentationNeeded(decl)
|
||||
and forall(SummaryXmlComment c | c=getADeclarationXmlComment(decl) |
|
||||
forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset) ) )
|
||||
and not getADeclarationXmlComment(decl) instanceof InheritDocXmlComment
|
||||
where
|
||||
declarationHasXmlComment(decl) and
|
||||
isDocumentationNeeded(decl) and
|
||||
forall(SummaryXmlComment c | c = getADeclarationXmlComment(decl) |
|
||||
forall(int offset | c.isOpenTag(offset) | c.isEmptyTag(offset))
|
||||
) and
|
||||
not getADeclarationXmlComment(decl) instanceof InheritDocXmlComment
|
||||
select decl, "Documentation should have a summary."
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
import Documentation
|
||||
|
||||
from UnboundGeneric d, TypeParameter p
|
||||
where p=d.getATypeParameter()
|
||||
and declarationHasXmlComment(d)
|
||||
and not exists(TypeparamXmlComment comment, int offset |
|
||||
comment = getADeclarationXmlComment(d)
|
||||
and comment.getName(offset) = p.getName()
|
||||
and comment.hasBody(offset) )
|
||||
and not getADeclarationXmlComment(d) instanceof InheritDocXmlComment
|
||||
where
|
||||
p = d.getATypeParameter() and
|
||||
declarationHasXmlComment(d) and
|
||||
not exists(TypeparamXmlComment comment, int offset |
|
||||
comment = getADeclarationXmlComment(d) and
|
||||
comment.getName(offset) = p.getName() and
|
||||
comment.hasBody(offset)
|
||||
) and
|
||||
not getADeclarationXmlComment(d) instanceof InheritDocXmlComment
|
||||
select p, "Type parameter should be documented."
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
* frameworks/asp.net
|
||||
* external/cwe/cwe-434
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from PropertyAccess pa
|
||||
where pa.getTarget().hasName("PostedFile")
|
||||
and pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.UI.HtmlControls", "HtmlInputFile")
|
||||
where
|
||||
pa.getTarget().hasName("PostedFile") and
|
||||
pa.getTarget().getDeclaringType().hasQualifiedName("System.Web.UI.HtmlControls", "HtmlInputFile")
|
||||
select pa, "Avoid using file upload."
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
* maintainability
|
||||
* frameworks/asp.net
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.system.web.Http
|
||||
|
||||
from IndexerAccess ia
|
||||
where ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest")
|
||||
and not isServerVariable(ia.getIndex(0))
|
||||
where
|
||||
ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") and
|
||||
not isServerVariable(ia.getIndex(0))
|
||||
select ia, "Ambiguous access to variable."
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
* maintainability
|
||||
* frameworks/asp.net
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.system.web.Http
|
||||
|
||||
from IndexerAccess ia
|
||||
where ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest")
|
||||
and isServerVariable(ia.getIndex(0))
|
||||
where
|
||||
ia.getTarget().getDeclaringType().hasQualifiedName("System.Web", "HttpRequest") and
|
||||
isServerVariable(ia.getIndex(0))
|
||||
select ia, "Ambiguous access to server variable."
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
import csharp
|
||||
|
||||
from ExplicitCast c, ConstructedType src, TypeParameter dest
|
||||
where c.getExpr() instanceof ThisAccess
|
||||
and src = c.getExpr().getType()
|
||||
and dest = c.getTargetType()
|
||||
and dest = src.getUnboundGeneric().getATypeParameter()
|
||||
select c, "Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.",
|
||||
dest, dest.getName(),
|
||||
src, src.getName()
|
||||
where
|
||||
c.getExpr() instanceof ThisAccess and
|
||||
src = c.getExpr().getType() and
|
||||
dest = c.getTargetType() and
|
||||
dest = src.getUnboundGeneric().getATypeParameter()
|
||||
select c,
|
||||
"Casting 'this' to $@, a type parameter of $@, masks an implicit type constraint that should be explicitly stated.",
|
||||
dest, dest.getName(), src, src.getName()
|
||||
|
|
|
@ -19,16 +19,18 @@ class GenericCatchClause extends CatchClause {
|
|||
this instanceof GeneralCatchClause
|
||||
or
|
||||
this = any(SpecificCatchClause scc |
|
||||
scc.getCaughtExceptionType() instanceof SystemExceptionClass and
|
||||
not scc.hasFilterClause()
|
||||
)
|
||||
scc.getCaughtExceptionType() instanceof SystemExceptionClass and
|
||||
not scc.hasFilterClause()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from GenericCatchClause gcc
|
||||
where forall(ThrowStmt throw |
|
||||
// ok to catch all exceptions if they may be rethrown
|
||||
gcc.getBlock().getAChildStmt+() = throw |
|
||||
exists(throw.getExpr())
|
||||
)
|
||||
where
|
||||
forall(ThrowStmt throw |
|
||||
// ok to catch all exceptions if they may be rethrown
|
||||
gcc.getBlock().getAChildStmt+() = throw
|
||||
|
|
||||
exists(throw.getExpr())
|
||||
)
|
||||
select gcc, "Generic catch clause."
|
||||
|
|
|
@ -15,25 +15,20 @@ import csharp
|
|||
|
||||
int isCountForIfChain(IfStmt is) {
|
||||
exists(int rest |
|
||||
(if is.getElse() instanceof IfStmt then rest = isCountForIfChain(is.getElse()) else rest = 0) and
|
||||
(
|
||||
if is.getElse() instanceof IfStmt then
|
||||
rest = isCountForIfChain(is.getElse())
|
||||
else
|
||||
rest = 0
|
||||
)
|
||||
and
|
||||
(
|
||||
if is.getCondition().(IsTypeExpr).getCheckedType().getSourceDeclaration().fromSource() then
|
||||
result = 1 + rest
|
||||
else
|
||||
result = rest
|
||||
if is.getCondition().(IsTypeExpr).getCheckedType().getSourceDeclaration().fromSource()
|
||||
then result = 1 + rest
|
||||
else result = rest
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from IfStmt is, int n
|
||||
where
|
||||
n = isCountForIfChain(is)
|
||||
and n > 5
|
||||
and not exists(IfStmt other | is = other.getElse())
|
||||
select is, "This if block performs a chain of " + n + " type tests - consider alternatives, e.g. polymorphism or the visitor pattern."
|
||||
n = isCountForIfChain(is) and
|
||||
n > 5 and
|
||||
not exists(IfStmt other | is = other.getElse())
|
||||
select is,
|
||||
"This if block performs a chain of " + n +
|
||||
" type tests - consider alternatives, e.g. polymorphism or the visitor pattern."
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
import csharp
|
||||
|
||||
from ExplicitCast c, ValueOrRefType src, ValueOrRefType dest
|
||||
where c.getExpr() instanceof ThisAccess
|
||||
and src = c.getExpr().getType()
|
||||
and dest = c.getTargetType()
|
||||
and src = dest.getABaseType+()
|
||||
where
|
||||
c.getExpr() instanceof ThisAccess and
|
||||
src = c.getExpr().getType() and
|
||||
dest = c.getTargetType() and
|
||||
src = dest.getABaseType+()
|
||||
select c, "Downcasting 'this' from $@ to $@ introduces a dependency cycle between the two types.",
|
||||
src, src.getName(),
|
||||
dest, dest.getName()
|
||||
src, src.getName(), dest, dest.getName()
|
||||
|
|
|
@ -15,11 +15,11 @@ import semmle.code.csharp.commons.Assertions
|
|||
|
||||
from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct
|
||||
where
|
||||
ise.getExpr() instanceof ThisAccess
|
||||
and t = ise.getExpr().getType()
|
||||
and ct = ise.getCheckedType()
|
||||
and ct.getABaseType*() = t
|
||||
and not isExprInAssertion(ise)
|
||||
select ise, "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.",
|
||||
ct, ct.getName(),
|
||||
t, t.getName()
|
||||
ise.getExpr() instanceof ThisAccess and
|
||||
t = ise.getExpr().getType() and
|
||||
ct = ise.getCheckedType() and
|
||||
ct.getABaseType*() = t and
|
||||
not isExprInAssertion(ise)
|
||||
select ise,
|
||||
"Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.",
|
||||
ct, ct.getName(), t, t.getName()
|
||||
|
|
|
@ -17,10 +17,7 @@ import semmle.code.csharp.frameworks.system.Collections
|
|||
import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
|
||||
predicate lambdaCaptures(AnonymousFunctionExpr lambda, Variable v) {
|
||||
exists(VariableAccess va |
|
||||
va.getEnclosingCallable() = lambda |
|
||||
va.getTarget() = v
|
||||
)
|
||||
exists(VariableAccess va | va.getEnclosingCallable() = lambda | va.getTarget() = v)
|
||||
}
|
||||
|
||||
predicate lambdaCapturesLoopVariable(AnonymousFunctionExpr lambda, ForeachStmt loop, Variable v) {
|
||||
|
@ -33,41 +30,34 @@ predicate inForeachStmtBody(ForeachStmt loop, Element e) {
|
|||
e = loop.getBody()
|
||||
or
|
||||
exists(Element mid |
|
||||
inForeachStmtBody(loop, mid)
|
||||
and
|
||||
inForeachStmtBody(loop, mid) and
|
||||
e = mid.getAChild()
|
||||
)
|
||||
}
|
||||
|
||||
class LambdaDataFlowConfiguration extends DataFlow::Configuration {
|
||||
LambdaDataFlowConfiguration() {
|
||||
this = "LambdaDataFlowConfiguration"
|
||||
}
|
||||
LambdaDataFlowConfiguration() { this = "LambdaDataFlowConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
lambdaCapturesLoopVariable(source.asExpr(), _, _)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(getAssignmentTarget(sink.asExpr()))
|
||||
}
|
||||
override predicate isSink(DataFlow::Node sink) { exists(getAssignmentTarget(sink.asExpr())) }
|
||||
|
||||
predicate capturesLoopVarAndIsStoredIn(AnonymousFunctionExpr lambda, Variable loopVar, Element storage) {
|
||||
exists(DataFlow::Node sink |
|
||||
this.hasFlow(DataFlow::exprNode(lambda), sink) |
|
||||
predicate capturesLoopVarAndIsStoredIn(
|
||||
AnonymousFunctionExpr lambda, Variable loopVar, Element storage
|
||||
) {
|
||||
exists(DataFlow::Node sink | this.hasFlow(DataFlow::exprNode(lambda), sink) |
|
||||
storage = getAssignmentTarget(sink.asExpr())
|
||||
)
|
||||
and
|
||||
exists(ForeachStmt loop |
|
||||
lambdaCapturesLoopVariable(lambda, loop, loopVar) |
|
||||
) and
|
||||
exists(ForeachStmt loop | lambdaCapturesLoopVariable(lambda, loop, loopVar) |
|
||||
not declaredInsideLoop(loop, storage)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Element getAssignmentTarget(Expr e) {
|
||||
exists(Assignment a |
|
||||
a.getRValue() = e |
|
||||
exists(Assignment a | a.getRValue() = e |
|
||||
result = a.getLValue().(PropertyAccess).getTarget() or
|
||||
result = a.getLValue().(FieldAccess).getTarget() or
|
||||
result = a.getLValue().(LocalVariableAccess).getTarget() or
|
||||
|
@ -84,19 +74,16 @@ Element getAssignmentTarget(Expr e) {
|
|||
|
||||
Element getCollectionAssignmentTarget(Expr e) {
|
||||
// Store into collection via method
|
||||
exists(MethodCall mc, Method m, IEnumerableFlow ief, CallableFlowSourceArg source, CallableFlowSinkQualifier sink, int i |
|
||||
mc.getQualifier() = result.(Variable).getAnAccess()
|
||||
and
|
||||
ief = mc.getQualifier().getType().getSourceDeclaration()
|
||||
and
|
||||
m = mc.getTarget().getSourceDeclaration()
|
||||
and
|
||||
ief.callableFlow(source, sink, m, _)
|
||||
and
|
||||
source.getCallable() = m
|
||||
and
|
||||
source.getArgumentIndex() = i
|
||||
and
|
||||
exists(
|
||||
MethodCall mc, Method m, IEnumerableFlow ief, CallableFlowSourceArg source,
|
||||
CallableFlowSinkQualifier sink, int i
|
||||
|
|
||||
mc.getQualifier() = result.(Variable).getAnAccess() and
|
||||
ief = mc.getQualifier().getType().getSourceDeclaration() and
|
||||
m = mc.getTarget().getSourceDeclaration() and
|
||||
ief.callableFlow(source, sink, m, _) and
|
||||
source.getCallable() = m and
|
||||
source.getArgumentIndex() = i and
|
||||
e = mc.getArgument(i)
|
||||
)
|
||||
or
|
||||
|
@ -104,26 +91,29 @@ Element getCollectionAssignmentTarget(Expr e) {
|
|||
e = result.(ArrayCreation).getInitializer().getAnElement()
|
||||
or
|
||||
// Collection initializer
|
||||
e = result.(ObjectCreation).getInitializer().(CollectionInitializer).getElementInitializer(_).getAnArgument()
|
||||
e = result
|
||||
.(ObjectCreation)
|
||||
.getInitializer()
|
||||
.(CollectionInitializer)
|
||||
.getElementInitializer(_)
|
||||
.getAnArgument()
|
||||
or
|
||||
// Store values using indexer
|
||||
exists(IndexerAccess ia, AssignExpr ae |
|
||||
ia.getQualifier() = result.(Variable).getAnAccess()
|
||||
and
|
||||
ia = ae.getLValue()
|
||||
and
|
||||
ia.getQualifier() = result.(Variable).getAnAccess() and
|
||||
ia = ae.getLValue() and
|
||||
e = ae.getRValue()
|
||||
)
|
||||
}
|
||||
|
||||
// Variable v is declared inside the loop body
|
||||
predicate declaredInsideLoop(ForeachStmt loop, LocalVariable v) {
|
||||
exists(LocalVariableDeclStmt decl |
|
||||
decl.getVariableDeclExpr(_).getVariable() = v |
|
||||
exists(LocalVariableDeclStmt decl | decl.getVariableDeclExpr(_).getVariable() = v |
|
||||
inForeachStmtBody(loop, decl)
|
||||
)
|
||||
}
|
||||
|
||||
from LambdaDataFlowConfiguration c, AnonymousFunctionExpr lambda, Variable loopVar, Element storage
|
||||
where c.capturesLoopVarAndIsStoredIn(lambda, loopVar, storage)
|
||||
select lambda, "Function which may be stored in $@ captures variable $@", storage, storage.toString(), loopVar, loopVar.getName()
|
||||
select lambda, "Function which may be stored in $@ captures variable $@", storage,
|
||||
storage.toString(), loopVar, loopVar.getName()
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
import csharp
|
||||
|
||||
predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) {
|
||||
def.getTarget().getSourceDeclaration() = f
|
||||
and
|
||||
def.getTarget().getSourceDeclaration() = f and
|
||||
(
|
||||
def.getEnclosingCallable().(Constructor).getDeclaringType() = f.getDeclaringType()
|
||||
or
|
||||
|
@ -23,15 +22,15 @@ predicate isReadonlyCompatibleDefinition(AssignableDefinition def, Field f) {
|
|||
}
|
||||
|
||||
predicate canBeReadonly(Field f) {
|
||||
forex(AssignableDefinition def |
|
||||
def.getTarget().getSourceDeclaration() = f |
|
||||
forex(AssignableDefinition def | def.getTarget().getSourceDeclaration() = f |
|
||||
isReadonlyCompatibleDefinition(def, f)
|
||||
)
|
||||
}
|
||||
|
||||
from Field f
|
||||
where canBeReadonly(f)
|
||||
and not f.isConst()
|
||||
and not f.isReadOnly()
|
||||
and (f.isEffectivelyPrivate() or f.isEffectivelyInternal())
|
||||
where
|
||||
canBeReadonly(f) and
|
||||
not f.isConst() and
|
||||
not f.isReadOnly() and
|
||||
(f.isEffectivelyPrivate() or f.isEffectivelyInternal())
|
||||
select f, "Field '" + f.getName() + "' can be 'readonly'."
|
||||
|
|
|
@ -13,25 +13,21 @@ import csharp
|
|||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() {
|
||||
this = "MissedTernaryOpportunity"
|
||||
}
|
||||
StructuralComparisonConfig() { this = "MissedTernaryOpportunity" }
|
||||
|
||||
override predicate candidate(Element x, Element y) {
|
||||
exists(IfStmt is, AssignExpr ae1 |
|
||||
ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
x = ae1.getLValue()
|
||||
and
|
||||
exists(AssignExpr ae2 |
|
||||
ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr()
|
||||
|
|
||||
x = ae1.getLValue() and
|
||||
exists(AssignExpr ae2 | ae2 = is.getElse().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
y = ae2.getLValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
IfStmt getIfStmt() {
|
||||
exists(AssignExpr ae |
|
||||
ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
exists(AssignExpr ae | ae = result.getThen().stripSingletonBlocks().(ExprStmt).getExpr() |
|
||||
same(ae.getLValue(), _)
|
||||
)
|
||||
}
|
||||
|
@ -41,14 +37,16 @@ from IfStmt is, string what
|
|||
where
|
||||
(
|
||||
(
|
||||
is.getThen().stripSingletonBlocks() instanceof ReturnStmt
|
||||
and is.getElse().stripSingletonBlocks() instanceof ReturnStmt
|
||||
and what = "return"
|
||||
is.getThen().stripSingletonBlocks() instanceof ReturnStmt and
|
||||
is.getElse().stripSingletonBlocks() instanceof ReturnStmt and
|
||||
what = "return"
|
||||
)
|
||||
or exists(StructuralComparisonConfig c |
|
||||
is = c.getIfStmt()
|
||||
and what = "write to the same variable"
|
||||
or
|
||||
exists(StructuralComparisonConfig c |
|
||||
is = c.getIfStmt() and
|
||||
what = "write to the same variable"
|
||||
)
|
||||
)
|
||||
and not exists(IfStmt other | is = other.getElse())
|
||||
select is, "Both branches of this 'if' statement " + what + " - consider using '?' to express intent better."
|
||||
) and
|
||||
not exists(IfStmt other | is = other.getElse())
|
||||
select is,
|
||||
"Both branches of this 'if' statement " + what + " - consider using '?' to express intent better."
|
||||
|
|
|
@ -13,27 +13,22 @@ import csharp
|
|||
import semmle.code.csharp.frameworks.System
|
||||
|
||||
/** A call to IDisposable.Dispose or a method that overrides it. */
|
||||
class DisposeCall extends MethodCall
|
||||
{
|
||||
DisposeCall()
|
||||
{
|
||||
getTarget() instanceof DisposeMethod
|
||||
}
|
||||
class DisposeCall extends MethodCall {
|
||||
DisposeCall() { getTarget() instanceof DisposeMethod }
|
||||
|
||||
/** The object being disposed by the call (provided it can be easily determined). */
|
||||
Variable getDisposee()
|
||||
{
|
||||
Variable getDisposee() {
|
||||
exists(VariableAccess va |
|
||||
va = getQualifier().stripCasts()
|
||||
and result = va.getTarget()
|
||||
va = getQualifier().stripCasts() and
|
||||
result = va.getTarget()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from Variable v, DisposeCall c, TryStmt ts
|
||||
where
|
||||
v = c.getDisposee()
|
||||
and c = ts.getFinally().getAChild*()
|
||||
select v, "This variable is manually $@ in a $@ - consider a C# using statement as a preferable resource management technique.",
|
||||
c, "disposed",
|
||||
ts.getFinally(), "finally block"
|
||||
v = c.getDisposee() and
|
||||
c = ts.getFinally().getAChild*()
|
||||
select v,
|
||||
"This variable is manually $@ in a $@ - consider a C# using statement as a preferable resource management technique.",
|
||||
c, "disposed", ts.getFinally(), "finally block"
|
||||
|
|
|
@ -13,9 +13,7 @@ import csharp
|
|||
|
||||
from IfStmt outer, IfStmt inner
|
||||
where
|
||||
inner = outer.getThen().stripSingletonBlocks()
|
||||
and
|
||||
not exists(outer.getElse())
|
||||
and
|
||||
inner = outer.getThen().stripSingletonBlocks() and
|
||||
not exists(outer.getElse()) and
|
||||
not exists(inner.getElse())
|
||||
select outer, "These 'if' statements can be combined."
|
||||
|
|
|
@ -13,19 +13,18 @@
|
|||
|
||||
import csharp
|
||||
|
||||
CatchClause containingCatchClause(Stmt s)
|
||||
{
|
||||
CatchClause containingCatchClause(Stmt s) {
|
||||
result.getBlock() = s
|
||||
or
|
||||
exists(Stmt mid |
|
||||
result = containingCatchClause(mid)
|
||||
and
|
||||
mid.getAChildStmt() = s
|
||||
and
|
||||
not mid instanceof CatchClause)
|
||||
result = containingCatchClause(mid) and
|
||||
mid.getAChildStmt() = s and
|
||||
not mid instanceof CatchClause
|
||||
)
|
||||
}
|
||||
|
||||
from SpecificCatchClause cc, ThrowStmt throw
|
||||
where throw.getExpr() = cc.getVariable().getAnAccess()
|
||||
and containingCatchClause(throw) = cc
|
||||
where
|
||||
throw.getExpr() = cc.getVariable().getAnAccess() and
|
||||
containingCatchClause(throw) = cc
|
||||
select throw, "Rethrowing exception variable."
|
||||
|
|
|
@ -16,8 +16,7 @@ import csharp
|
|||
* No other child nodes are boolean literals.
|
||||
*/
|
||||
predicate literalChild(Expr expr, int child, boolean value) {
|
||||
value = expr.getChild(child).(BoolLiteral).getBoolValue()
|
||||
and
|
||||
value = expr.getChild(child).(BoolLiteral).getBoolValue() and
|
||||
forall(int c | c != child | not expr.getChild(c) instanceof BoolLiteral)
|
||||
}
|
||||
|
||||
|
@ -26,10 +25,8 @@ predicate literalChild(Expr expr, int child, boolean value) {
|
|||
* No other child nodes are boolean literals.
|
||||
*/
|
||||
predicate literalChildren(Expr expr, int child1, boolean value1, int child2, boolean value2) {
|
||||
value1 = expr.getChild(child1).(BoolLiteral).getBoolValue()
|
||||
and
|
||||
value2 = expr.getChild(child2).(BoolLiteral).getBoolValue()
|
||||
and
|
||||
value1 = expr.getChild(child1).(BoolLiteral).getBoolValue() and
|
||||
value2 = expr.getChild(child2).(BoolLiteral).getBoolValue() and
|
||||
forall(int c | c != child1 and c != child2 | not expr.getChild(c) instanceof BoolLiteral)
|
||||
}
|
||||
|
||||
|
@ -40,7 +37,10 @@ predicate rewriteBinaryExpr(BinaryOperation op, boolean value, string oldPattern
|
|||
}
|
||||
|
||||
bindingset[withFalseOperand, withTrueOperand]
|
||||
predicate rewriteBinaryExpr(BinaryOperation op, string oldPattern, string withFalseOperand, string withTrueOperand, string newPattern) {
|
||||
predicate rewriteBinaryExpr(
|
||||
BinaryOperation op, string oldPattern, string withFalseOperand, string withTrueOperand,
|
||||
string newPattern
|
||||
) {
|
||||
rewriteBinaryExpr(op, false, oldPattern) and newPattern = withFalseOperand
|
||||
or
|
||||
rewriteBinaryExpr(op, true, oldPattern) and newPattern = withTrueOperand
|
||||
|
@ -55,7 +55,9 @@ predicate rewriteConditionalExpr(ConditionalExpr cond, string oldPattern, string
|
|||
or
|
||||
literalChild(cond, 2, true) and oldPattern = "A ? B : true" and newPattern = "!A || B"
|
||||
or
|
||||
exists(boolean b | literalChildren(cond, 1, b, 2, b) | oldPattern = "A ? " + b + " : " + b and newPattern = b.toString())
|
||||
exists(boolean b | literalChildren(cond, 1, b, 2, b) |
|
||||
oldPattern = "A ? " + b + " : " + b and newPattern = b.toString()
|
||||
)
|
||||
or
|
||||
literalChildren(cond, 1, true, 2, false) and oldPattern = "A ? true : false" and newPattern = "A"
|
||||
or
|
||||
|
@ -86,19 +88,18 @@ predicate pushNegation(LogicalNotExpr expr, string oldPattern, string newPattern
|
|||
expr.getOperand() instanceof LogicalNotExpr and oldPattern = "!!A" and newPattern = "A"
|
||||
or
|
||||
exists(string oldOperator, string newOperator |
|
||||
oldOperator = expr.getOperand().(BinaryOperation).getOperator()
|
||||
and
|
||||
oldOperator = expr.getOperand().(BinaryOperation).getOperator() and
|
||||
negatedOperators(oldOperator, newOperator)
|
||||
|
|
||||
oldPattern = "!(A " + oldOperator + " B)"
|
||||
and
|
||||
|
|
||||
oldPattern = "!(A " + oldOperator + " B)" and
|
||||
newPattern = "A " + newOperator + " B"
|
||||
)
|
||||
}
|
||||
|
||||
predicate rewrite(Expr expr, string oldPattern, string newPattern) {
|
||||
exists(string withFalseOperand, string withTrueOperand |
|
||||
simplifyBinaryExpr(expr.(BinaryOperation).getOperator(), withFalseOperand, withTrueOperand) |
|
||||
simplifyBinaryExpr(expr.(BinaryOperation).getOperator(), withFalseOperand, withTrueOperand)
|
||||
|
|
||||
rewriteBinaryExpr(expr, oldPattern, withFalseOperand, withTrueOperand, newPattern)
|
||||
)
|
||||
or
|
||||
|
@ -108,8 +109,9 @@ predicate rewrite(Expr expr, string oldPattern, string newPattern) {
|
|||
}
|
||||
|
||||
from Expr expr, string oldPattern, string newPattern, string action
|
||||
where rewrite(expr, oldPattern, newPattern)
|
||||
and if newPattern = "true" or newPattern = "false"
|
||||
where
|
||||
rewrite(expr, oldPattern, newPattern) and
|
||||
if newPattern = "true" or newPattern = "false"
|
||||
then action = "is always"
|
||||
else action = "can be simplified to"
|
||||
select expr, "The expression '" + oldPattern + "' " + action + " '" + newPattern + "'."
|
||||
|
|
|
@ -14,10 +14,11 @@
|
|||
import csharp
|
||||
|
||||
from Setter setter
|
||||
where not exists(setter.getAParameter().getAnAccess())
|
||||
and not exists(ThrowStmt t | t.getEnclosingCallable()=setter)
|
||||
and setter.hasBody() // Trivial setter is OK
|
||||
and not setter.getDeclaration().overrides()
|
||||
and not setter.getDeclaration().implements()
|
||||
and not setter.getDeclaration().isVirtual()
|
||||
where
|
||||
not exists(setter.getAParameter().getAnAccess()) and
|
||||
not exists(ThrowStmt t | t.getEnclosingCallable() = setter) and
|
||||
setter.hasBody() and // Trivial setter is OK
|
||||
not setter.getDeclaration().overrides() and
|
||||
not setter.getDeclaration().implements() and
|
||||
not setter.getDeclaration().isVirtual()
|
||||
select setter, "Value ignored when setting property."
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
import csharp
|
||||
|
||||
from ExplicitCast cast, Expr e, Type type
|
||||
where e = cast.getExpr()
|
||||
and type = cast.getTargetType()
|
||||
and type = e.getType()
|
||||
and not type instanceof NullType
|
||||
and not e.(ImplicitDelegateCreation).getArgument() instanceof AnonymousFunctionExpr
|
||||
where
|
||||
e = cast.getExpr() and
|
||||
type = cast.getTargetType() and
|
||||
type = e.getType() and
|
||||
not type instanceof NullType and
|
||||
not e.(ImplicitDelegateCreation).getArgument() instanceof AnonymousFunctionExpr
|
||||
select cast, "This cast is redundant because the expression already has type " + type + "."
|
||||
|
|
|
@ -14,20 +14,15 @@ import csharp
|
|||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() {
|
||||
this = "UselessIsBeforeAs"
|
||||
}
|
||||
StructuralComparisonConfig() { this = "UselessIsBeforeAs" }
|
||||
|
||||
override predicate candidate(Element x, Element y) {
|
||||
exists(IfStmt is, AsExpr ae, IsTypeExpr ie |
|
||||
ie = is.getCondition().getAChild*()
|
||||
and
|
||||
ae.getTargetType() = ie.getCheckedType()
|
||||
and
|
||||
x = ie.getExpr()
|
||||
and
|
||||
ie = is.getCondition().getAChild*() and
|
||||
ae.getTargetType() = ie.getCheckedType() and
|
||||
x = ie.getExpr() and
|
||||
y = ae.getExpr()
|
||||
|
|
||||
|
|
||||
ae = is.getThen().getAChild*()
|
||||
or
|
||||
ae = is.getElse().getAChild*()
|
||||
|
@ -36,10 +31,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
|||
|
||||
predicate uselessIsBeforeAs(AsExpr ae, IsExpr ie) {
|
||||
exists(Expr x, Expr y |
|
||||
same(x, y)
|
||||
and
|
||||
ie.getExpr() = x
|
||||
and
|
||||
same(x, y) and
|
||||
ie.getExpr() = x and
|
||||
ae.getExpr() = y
|
||||
)
|
||||
}
|
||||
|
@ -47,8 +40,8 @@ class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
|||
|
||||
from AsExpr ae, IsExpr ie
|
||||
where
|
||||
exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie))
|
||||
and
|
||||
exists(StructuralComparisonConfig c | c.uselessIsBeforeAs(ae, ie)) and
|
||||
not exists(MethodCall mc | ae = mc.getAnArgument().getAChildExpr*())
|
||||
select ae, "This 'as' expression performs a type test - it should be directly compared against null, rendering the 'is' $@ potentially redundant.",
|
||||
select ae,
|
||||
"This 'as' expression performs a type test - it should be directly compared against null, rendering the 'is' $@ potentially redundant.",
|
||||
ie, "here"
|
||||
|
|
|
@ -15,23 +15,19 @@ import csharp
|
|||
import semmle.code.csharp.commons.StructuralComparison
|
||||
|
||||
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
|
||||
StructuralComparisonConfig() {
|
||||
this = "UselessNullCoalescingExpression"
|
||||
}
|
||||
StructuralComparisonConfig() { this = "UselessNullCoalescingExpression" }
|
||||
|
||||
override predicate candidate(Element x, Element y) {
|
||||
exists(NullCoalescingExpr nce |
|
||||
x.(Access) = nce.getLeftOperand()
|
||||
and
|
||||
x.(Access) = nce.getLeftOperand() and
|
||||
y.(Access) = nce.getRightOperand().getAChildExpr*()
|
||||
)
|
||||
}
|
||||
|
||||
NullCoalescingExpr getUselessNullCoalescingExpr() {
|
||||
exists(AssignableAccess x |
|
||||
result.getLeftOperand() = x
|
||||
and
|
||||
forex(AssignableAccess y | same(x,y) | y instanceof AssignableRead and not y.isRefArgument())
|
||||
result.getLeftOperand() = x and
|
||||
forex(AssignableAccess y | same(x, y) | y instanceof AssignableRead and not y.isRefArgument())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,9 @@ import csharp
|
|||
|
||||
from IsTypeExpr ise, ValueOrRefType t, ValueOrRefType ct
|
||||
where
|
||||
t = ise.getExpr().getType()
|
||||
and ct = ise.getCheckedType()
|
||||
and ct = t.getABaseType+()
|
||||
select ise, "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.",
|
||||
t, t.getName(),
|
||||
ct, ct.getName()
|
||||
t = ise.getExpr().getType() and
|
||||
ct = ise.getCheckedType() and
|
||||
ct = t.getABaseType+()
|
||||
select ise,
|
||||
"There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t,
|
||||
t.getName(), ct, ct.getName()
|
||||
|
|
|
@ -13,17 +13,11 @@
|
|||
import csharp
|
||||
|
||||
/** A static callable. */
|
||||
class StaticCallable extends Callable {
|
||||
StaticCallable() {
|
||||
this.(Modifiable).isStatic()
|
||||
}
|
||||
}
|
||||
class StaticCallable extends Callable { StaticCallable() { this.(Modifiable).isStatic() } }
|
||||
|
||||
/** An instance callable, that is, a non-static callable. */
|
||||
class InstanceCallable extends Callable {
|
||||
InstanceCallable() {
|
||||
not this instanceof StaticCallable
|
||||
}
|
||||
InstanceCallable() { not this instanceof StaticCallable }
|
||||
}
|
||||
|
||||
/** A call to a static callable. */
|
||||
|
@ -35,21 +29,21 @@ class StaticCall extends Call {
|
|||
}
|
||||
|
||||
/** Holds `t` has instance callable `c` as a member, with name `name`. */
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
predicate hasInstanceCallable(ValueOrRefType t, InstanceCallable c, string name) {
|
||||
t.hasMember(c) and
|
||||
name = c.getName()
|
||||
}
|
||||
|
||||
/** Holds if extension method `m` is a method on `t` with name `name`. */
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
predicate hasExtensionMethod(ValueOrRefType t, ExtensionMethod m, string name) {
|
||||
t.isImplicitlyConvertibleTo(m.getExtendedType()) and
|
||||
name = m.getName()
|
||||
}
|
||||
|
||||
/** Holds `t` has static callable `c` as a member, with name `name`. */
|
||||
pragma [noinline]
|
||||
pragma[noinline]
|
||||
predicate hasStaticCallable(ValueOrRefType t, StaticCallable c, string name) {
|
||||
t.hasMember(c) and
|
||||
name = c.getName()
|
||||
|
@ -58,9 +52,9 @@ predicate hasStaticCallable(ValueOrRefType t, StaticCallable c, string name) {
|
|||
/** Gets the minimum number of arguments required to call `c`. */
|
||||
int getMinimumArguments(Callable c) {
|
||||
result = count(Parameter p |
|
||||
p = c.getAParameter() and
|
||||
not p.hasDefaultValue()
|
||||
)
|
||||
p = c.getAParameter() and
|
||||
not p.hasDefaultValue()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the maximum number of arguments allowed to call `c`, if any. */
|
||||
|
@ -72,6 +66,7 @@ int getMaximumArguments(Callable c) {
|
|||
/** An explicit upcast. */
|
||||
class ExplicitUpcast extends ExplicitCast {
|
||||
ValueOrRefType src;
|
||||
|
||||
ValueOrRefType dest;
|
||||
|
||||
ExplicitUpcast() {
|
||||
|
@ -93,10 +88,9 @@ class ExplicitUpcast extends ExplicitCast {
|
|||
}
|
||||
|
||||
/** Holds if this upcast may be used to disambiguate the target of an instance call. */
|
||||
pragma [nomagic]
|
||||
pragma[nomagic]
|
||||
private predicate isDisambiguatingInstanceCall(InstanceCallable other, int args) {
|
||||
exists(Call c, InstanceCallable target, ValueOrRefType t |
|
||||
this.isArgument(c, target) |
|
||||
exists(Call c, InstanceCallable target, ValueOrRefType t | this.isArgument(c, target) |
|
||||
t = c.(QualifiableExpr).getQualifier().getType() and
|
||||
hasInstanceCallable(t, other, target.getName()) and
|
||||
args = c.getNumberOfArguments() and
|
||||
|
@ -105,10 +99,11 @@ class ExplicitUpcast extends ExplicitCast {
|
|||
}
|
||||
|
||||
/** Holds if this upcast may be used to disambiguate the target of an extension method call. */
|
||||
pragma [nomagic]
|
||||
pragma[nomagic]
|
||||
private predicate isDisambiguatingExtensionCall(ExtensionMethod other, int args) {
|
||||
exists(ExtensionMethodCall c, ExtensionMethod target, ValueOrRefType t |
|
||||
this.isArgument(c, target) |
|
||||
this.isArgument(c, target)
|
||||
|
|
||||
not c.isOrdinaryStaticCall() and
|
||||
t = target.getParameter(0).getType() and
|
||||
hasExtensionMethod(t, other, target.getName()) and
|
||||
|
@ -117,8 +112,10 @@ class ExplicitUpcast extends ExplicitCast {
|
|||
)
|
||||
}
|
||||
|
||||
pragma [nomagic]
|
||||
private predicate isDisambiguatingStaticCall0(StaticCall c, StaticCallable target, string name, ValueOrRefType t) {
|
||||
pragma[nomagic]
|
||||
private predicate isDisambiguatingStaticCall0(
|
||||
StaticCall c, StaticCallable target, string name, ValueOrRefType t
|
||||
) {
|
||||
this.isArgument(c, target) and
|
||||
name = target.getName() and
|
||||
(
|
||||
|
@ -130,10 +127,11 @@ class ExplicitUpcast extends ExplicitCast {
|
|||
}
|
||||
|
||||
/** Holds if this upcast may be used to disambiguate the target of a static call. */
|
||||
pragma [nomagic]
|
||||
pragma[nomagic]
|
||||
private predicate isDisambiguatingStaticCall(StaticCallable other, int args) {
|
||||
exists(StaticCall c, StaticCallable target, ValueOrRefType t, string name |
|
||||
this.isDisambiguatingStaticCall0(c, target, name, t) |
|
||||
this.isDisambiguatingStaticCall0(c, target, name, t)
|
||||
|
|
||||
hasStaticCallable(t, other, name) and
|
||||
args = c.getNumberOfArguments() and
|
||||
other != target
|
||||
|
@ -148,7 +146,7 @@ class ExplicitUpcast extends ExplicitCast {
|
|||
this.isDisambiguatingExtensionCall(other, args)
|
||||
or
|
||||
this.isDisambiguatingStaticCall(other, args)
|
||||
|
|
||||
|
|
||||
args >= getMinimumArguments(other) and
|
||||
not args > getMaximumArguments(other)
|
||||
)
|
||||
|
@ -164,29 +162,27 @@ class ExplicitUpcast extends ExplicitCast {
|
|||
this = any(OperatorCall oc).getAnArgument()
|
||||
or
|
||||
this = any(Operation o |
|
||||
not o instanceof Assignment and
|
||||
not o instanceof UnaryBitwiseOperation and
|
||||
not o instanceof SizeofExpr and
|
||||
not o instanceof PointerIndirectionExpr and
|
||||
not o instanceof AddressOfExpr and
|
||||
not o instanceof UnaryLogicalOperation and
|
||||
not o instanceof BinaryBitwiseOperation and
|
||||
not o instanceof LogicalAndExpr and
|
||||
not o instanceof LogicalOrExpr
|
||||
).getAnOperand()
|
||||
not o instanceof Assignment and
|
||||
not o instanceof UnaryBitwiseOperation and
|
||||
not o instanceof SizeofExpr and
|
||||
not o instanceof PointerIndirectionExpr and
|
||||
not o instanceof AddressOfExpr and
|
||||
not o instanceof UnaryLogicalOperation and
|
||||
not o instanceof BinaryBitwiseOperation and
|
||||
not o instanceof LogicalAndExpr and
|
||||
not o instanceof LogicalOrExpr
|
||||
).getAnOperand()
|
||||
or
|
||||
this = any(LocalVariableDeclAndInitExpr decl |
|
||||
decl.isImplicitlyTyped()
|
||||
).getInitializer()
|
||||
this = any(LocalVariableDeclAndInitExpr decl | decl.isImplicitlyTyped()).getInitializer()
|
||||
or
|
||||
exists(LambdaExpr c | c.canReturn(this))
|
||||
}
|
||||
}
|
||||
|
||||
from ExplicitUpcast u, ValueOrRefType src, ValueOrRefType dest
|
||||
where src = u.getSourceType()
|
||||
and dest = u.getTargetType()
|
||||
and not u.isUseful()
|
||||
select u, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.",
|
||||
src, src.getName(),
|
||||
dest, dest.getName()
|
||||
where
|
||||
src = u.getSourceType() and
|
||||
dest = u.getTargetType() and
|
||||
not u.isUseful()
|
||||
select u, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", src,
|
||||
src.getName(), dest, dest.getName()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* @tags reliability
|
||||
* correctness
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
predicate isDefinitelyPositive(Expr e) {
|
||||
|
@ -18,11 +19,16 @@ predicate isDefinitelyPositive(Expr e) {
|
|||
}
|
||||
|
||||
from BinaryOperation t, RemExpr lhs, IntegerLiteral rhs, string parity
|
||||
where t.getLeftOperand() = lhs and
|
||||
t.getRightOperand() = rhs and
|
||||
not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and
|
||||
lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and
|
||||
((t instanceof EQExpr and rhs.getValue() = "1" and parity = "oddness") or
|
||||
(t instanceof NEExpr and rhs.getValue() = "1" and parity = "evenness") or
|
||||
(t instanceof GTExpr and rhs.getValue() = "0" and parity = "oddness"))
|
||||
where
|
||||
t.getLeftOperand() = lhs and
|
||||
t.getRightOperand() = rhs and
|
||||
not isDefinitelyPositive(lhs.getLeftOperand().stripCasts()) and
|
||||
lhs.getRightOperand().(IntegerLiteral).getValue() = "2" and
|
||||
(
|
||||
(t instanceof EQExpr and rhs.getValue() = "1" and parity = "oddness")
|
||||
or
|
||||
(t instanceof NEExpr and rhs.getValue() = "1" and parity = "evenness")
|
||||
or
|
||||
(t instanceof GTExpr and rhs.getValue() = "0" and parity = "oddness")
|
||||
)
|
||||
select t, "Possibly invalid test for " + parity + ". This will fail for negative numbers."
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче