diff --git a/infer/models/java/src/java/util/concurrent/ReentrantLock.java b/infer/models/java/src/java/util/concurrent/ReentrantLock.java index 3b3fb07b7..f2e2a8412 100644 --- a/infer/models/java/src/java/util/concurrent/ReentrantLock.java +++ b/infer/models/java/src/java/util/concurrent/ReentrantLock.java @@ -19,6 +19,7 @@ */ package java.util.concurrent.locks; +import java.util.concurrent.TimeUnit; import com.facebook.infer.builtins.InferBuiltins; import com.facebook.infer.builtins.InferUndefined; @@ -32,6 +33,41 @@ public abstract class ReentrantLock extends Lock implements java.io.Serializable InferBuiltins.__set_locked_attribute(this); } + /** + Sometimes doesn't get a lock. + */ + public void lockInterruptibly() throws InterruptedException { + if (InferUndefined.boolean_undefined()) { + InferBuiltins.__set_locked_attribute(this); + } else { + throw new InterruptedException(); + } + } + + /** + Again, doesn't always succeed + */ + public boolean tryLock() { + if (InferUndefined.boolean_undefined()) { + InferBuiltins.__set_locked_attribute(this); + return true; + } else { + return false; + } + } + + public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + if (InferUndefined.boolean_undefined()) {throw new InterruptedException();} + + if (InferUndefined.boolean_undefined()) { + InferBuiltins.__set_locked_attribute(this); + return true; + } else { + return false; + } + } + + /** * In some implementations (like ReentrantLock) an exception is thrown if the lock * is not held by the current thread. This model does not consider that possibility. diff --git a/infer/tests/build_systems/ant/issues.exp b/infer/tests/build_systems/ant/issues.exp index e49d1dd79..5da9ddabc 100644 --- a/infer/tests/build_systems/ant/issues.exp +++ b/infer/tests/build_systems/ant/issues.exp @@ -50,6 +50,8 @@ src/infer/GuardedByExample.java, Object GuardedByExample.byRefTrickyBad(), 5, UN src/infer/GuardedByExample.java, String GuardedByExample$3.readFromInnerClassBad1(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFromInnerClassBad1()] src/infer/GuardedByExample.java, String GuardedByExample$4.readFromInnerClassBad2(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFromInnerClassBad2()] src/infer/GuardedByExample.java, void GuardedByExample$Sub.badSub(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badSub()] +src/infer/GuardedByExample.java, void GuardedByExample.badGuardedByNormalLock(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badGuardedByNormalLock()] +src/infer/GuardedByExample.java, void GuardedByExample.badGuardedByReentrantLock(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badGuardedByReentrantLock()] src/infer/GuardedByExample.java, void GuardedByExample.readFAfterBlockBad(), 3, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFAfterBlockBad()] src/infer/GuardedByExample.java, void GuardedByExample.readFBad(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBad()] src/infer/GuardedByExample.java, void GuardedByExample.readFBadButSuppressedOther(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadButSuppressedOther()] diff --git a/infer/tests/build_systems/buck/issues.exp b/infer/tests/build_systems/buck/issues.exp index 4ecc4a43f..33de7b5aa 100644 --- a/infer/tests/build_systems/buck/issues.exp +++ b/infer/tests/build_systems/buck/issues.exp @@ -50,6 +50,8 @@ infer/tests/codetoanalyze/java/infer/GuardedByExample.java, Object GuardedByExam infer/tests/codetoanalyze/java/infer/GuardedByExample.java, String GuardedByExample$3.readFromInnerClassBad1(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFromInnerClassBad1()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, String GuardedByExample$4.readFromInnerClassBad2(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFromInnerClassBad2()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample$Sub.badSub(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badSub()] +infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.badGuardedByNormalLock(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badGuardedByNormalLock()] +infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.badGuardedByReentrantLock(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badGuardedByReentrantLock()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFAfterBlockBad(), 3, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFAfterBlockBad()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBad(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBad()] infer/tests/codetoanalyze/java/infer/GuardedByExample.java, void GuardedByExample.readFBadButSuppressedOther(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadButSuppressedOther()] diff --git a/infer/tests/codetoanalyze/java/infer/GuardedByExample.java b/infer/tests/codetoanalyze/java/infer/GuardedByExample.java index 39a07f7b1..da3d76582 100644 --- a/infer/tests/codetoanalyze/java/infer/GuardedByExample.java +++ b/infer/tests/codetoanalyze/java/infer/GuardedByExample.java @@ -16,6 +16,8 @@ import java.lang.annotation.Target; import com.google.common.annotations.VisibleForTesting; import android.annotation.SuppressLint; import javax.annotation.concurrent.GuardedBy; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -494,4 +496,43 @@ public class GuardedByExample { } + Lock normallock; + + @GuardedBy("normallock") + Integer guardedbynl; + + ReentrantLock reentrantlock; + + @GuardedBy("reentrantlock") + Integer guardedbyrel; + + + void goodGuardedByNormalLock() { + normallock.lock(); + guardedbynl = 22; + normallock.unlock(); + } + + void goodTryLockGuardedByNormalLock() { + if (normallock.tryLock()) { + guardedbynl = 22; + normallock.unlock(); + } + } + + void goodTryLockGuardedByReentrantLock() { + if (reentrantlock.tryLock()) { + guardedbyrel = 44; + reentrantlock.unlock(); + } + } + + void badGuardedByNormalLock(){ + guardedbynl = 22; + } + + void badGuardedByReentrantLock(){ + guardedbyrel = 44; + } + } diff --git a/infer/tests/codetoanalyze/java/infer/issues.exp b/infer/tests/codetoanalyze/java/infer/issues.exp index 6bb9dc532..b4c6c84fe 100644 --- a/infer/tests/codetoanalyze/java/infer/issues.exp +++ b/infer/tests/codetoanalyze/java/infer/issues.exp @@ -129,6 +129,8 @@ GuardedByExample.java, Object GuardedByExample.byRefTrickyBad(), 5, UNSAFE_GUARD GuardedByExample.java, String GuardedByExample$3.readFromInnerClassBad1(), 2, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFromInnerClassBad1()] GuardedByExample.java, String GuardedByExample$4.readFromInnerClassBad2(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFromInnerClassBad2()] GuardedByExample.java, void GuardedByExample$Sub.badSub(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badSub()] +GuardedByExample.java, void GuardedByExample.badGuardedByNormalLock(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badGuardedByNormalLock()] +GuardedByExample.java, void GuardedByExample.badGuardedByReentrantLock(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure badGuardedByReentrantLock()] GuardedByExample.java, void GuardedByExample.readFAfterBlockBad(), 3, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFAfterBlockBad()] GuardedByExample.java, void GuardedByExample.readFBad(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBad()] GuardedByExample.java, void GuardedByExample.readFBadButSuppressedOther(), 1, UNSAFE_GUARDED_BY_ACCESS, [start of procedure readFBadButSuppressedOther()]