mirror of
https://github.com/github/codeql.git
synced 2026-05-05 05:35:13 +02:00
115 lines
3.9 KiB
Plaintext
115 lines
3.9 KiB
Plaintext
/** Classes for concurrency queries. */
|
|
|
|
import csharp
|
|
|
|
private class WaitCall extends MethodCall {
|
|
WaitCall() {
|
|
this.getTarget().hasName("Wait") and
|
|
this.getTarget().getDeclaringType().hasQualifiedName("System.Threading", "Monitor")
|
|
}
|
|
|
|
Expr getExpr() { result = this.getArgument(0) }
|
|
}
|
|
|
|
/** An expression statement containing a `Wait` call. */
|
|
class WaitStmt extends ExprStmt {
|
|
WaitStmt() { this.getExpr() instanceof WaitCall }
|
|
|
|
/** Gets the expression that this wait call is waiting on. */
|
|
Expr getLock() { result = this.getExpr().(WaitCall).getExpr() }
|
|
|
|
/** Gets the variable that this wait call is waiting on, if any. */
|
|
Variable getWaitVariable() { result.getAnAccess() = this.getLock() }
|
|
|
|
/** Holds if this wait call waits on `this`. */
|
|
predicate isWaitThis() { this.getLock() instanceof ThisAccess }
|
|
|
|
/** Gets the type that this wait call waits on, if any. */
|
|
Type getWaitTypeObject() { result = this.getLock().(TypeofExpr).getTypeAccess().getTarget() }
|
|
}
|
|
|
|
private class SynchronizedMethodAttribute extends Attribute {
|
|
SynchronizedMethodAttribute() {
|
|
this.getType().hasQualifiedName("System.Runtime.CompilerServices", "MethodImplAttribute") and
|
|
exists(MemberConstantAccess a, MemberConstant mc |
|
|
a = this.getArgument(0) and
|
|
a.getTarget() = mc and
|
|
mc.hasName("Synchronized") and
|
|
mc.getDeclaringType().hasQualifiedName("System.Runtime.CompilerServices", "MethodImplOptions")
|
|
)
|
|
}
|
|
}
|
|
|
|
/** A method with attribute `[MethodImpl(MethodImplOptions.Synchronized)]`. */
|
|
private class SynchronizedMethod extends Method {
|
|
SynchronizedMethod() { this.getAnAttribute() instanceof SynchronizedMethodAttribute }
|
|
|
|
/** Holds if this method locks `this`. */
|
|
predicate isLockThis() { not this.isStatic() }
|
|
|
|
/** Gets the type that is locked by this method, if any. */
|
|
Type getLockTypeObject() { this.isStatic() and result = this.getDeclaringType() }
|
|
}
|
|
|
|
/** A block that is locked by a `lock` statement. */
|
|
abstract class LockedBlock extends BlockStmt {
|
|
/** Holds if the `lock` statement locks `this`. */
|
|
abstract predicate isLockThis();
|
|
|
|
/** Gets the lock variable of the `lock` statement, if any. */
|
|
abstract Variable getLockVariable();
|
|
|
|
/** Gets the locked type of the `lock` statement, if any. */
|
|
abstract Type getLockTypeObject();
|
|
|
|
/** Gets a statement in the scope of this locked block. */
|
|
Stmt getALockedStmt() {
|
|
// Do this instead of getParent+, because we don't want to escape
|
|
// delegates and lambdas
|
|
result.getParent() = this
|
|
or
|
|
exists(Stmt mid | mid = this.getALockedStmt() and result.getParent() = mid)
|
|
}
|
|
}
|
|
|
|
private class LockStmtBlock extends LockedBlock {
|
|
LockStmtBlock() { exists(LockStmt s | this = s.getBlock()) }
|
|
|
|
override predicate isLockThis() { exists(LockStmt s | this = s.getBlock() and s.isLockThis()) }
|
|
|
|
override Variable getLockVariable() {
|
|
exists(LockStmt s | this = s.getBlock() and result = s.getLockVariable())
|
|
}
|
|
|
|
override Type getLockTypeObject() {
|
|
exists(LockStmt s | this = s.getBlock() and result = s.getLockTypeObject())
|
|
}
|
|
}
|
|
|
|
/** A call that may take a lock using one of the standard library methods. */
|
|
class LockingCall extends MethodCall {
|
|
LockingCall() {
|
|
this.getTarget() =
|
|
any(Method m |
|
|
m.getDeclaringType().hasQualifiedName("System.Threading", "Monitor") and
|
|
m.getName().matches("%Enter%")
|
|
) or
|
|
this.getTarget().hasName("EnterReadLock") or
|
|
this.getTarget().hasName("EnterWriteLock")
|
|
}
|
|
}
|
|
|
|
private class SynchronizedMethodBlock extends LockedBlock {
|
|
SynchronizedMethodBlock() { exists(SynchronizedMethod m | this = m.getStatementBody()) }
|
|
|
|
override predicate isLockThis() {
|
|
exists(SynchronizedMethod m | this = m.getStatementBody() and m.isLockThis())
|
|
}
|
|
|
|
override Variable getLockVariable() { none() }
|
|
|
|
override Type getLockTypeObject() {
|
|
exists(SynchronizedMethod m | this = m.getStatementBody() and result = m.getLockTypeObject())
|
|
}
|
|
}
|