/** * @name Double-checked lock is not thread-safe * @description A repeated check on a non-volatile field is not thread-safe, and * could result in unexpected behavior. * @kind problem * @problem.severity error * @precision high * @id cs/unsafe-double-checked-lock * @tags correctness * concurrency * external/cwe/cwe-609 */ import csharp import semmle.code.csharp.commons.StructuralComparison class DoubleCheckedLock extends StructuralComparisonConfiguration { DoubleCheckedLock() { this="double checked lock" } override predicate candidate(Element x, Element y) { exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock | x = unlockedIf.getCondition() and y = lockedIf.getCondition() and lock = unlockedIf.getThen().stripSingletonBlocks() and lockedIf = lock.getBlock().stripSingletonBlocks() ) } } predicate doubleCheckedLock(Field field, IfStmt ifs) { 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*() ) } 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()