diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index 875b3b42d..cd4e952e4 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -37,7 +37,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct type lock_model = Lock | Unlock | LockedIfTrue | NoEffect - type thread_model = MainThread | MainThreadIfTrue | Unknown + type thread_model = BackgroundThread | MainThread | MainThreadIfTrue | UnknownThread type container_access_model = ContainerRead | ContainerWrite @@ -119,20 +119,18 @@ module TransferFunctions (CFG : ProcCfg.S) = struct -> NoEffect let get_thread_model = function - | Typ.Procname.Java java_pname - -> if is_thread_utils_type java_pname then - match Typ.Procname.java_get_method java_pname with - | "assertMainThread" | "checkOnMainThread" | "assertOnUiThread" - -> MainThread - | "isMainThread" | "isUiThread" - -> MainThreadIfTrue - | _ - -> Unknown - else Unknown - (* TODO: we can model this now *) - (* Note we are not modelling assertOnNonUiThread or assertOnBackgroundThread. These treated as Unknown *) + | Typ.Procname.Java java_pname when is_thread_utils_type java_pname -> ( + match Typ.Procname.java_get_method java_pname with + | "assertMainThread" | "assertOnUiThread" | "checkOnMainThread" + -> MainThread + | "isMainThread" | "isUiThread" + -> MainThreadIfTrue + | "assertOnBackgroundThread" | "assertOnNonUiThread" | "checkOnNonUiThread" + -> BackgroundThread + | _ + -> UnknownThread ) | _ - -> Unknown + -> UnknownThread let get_container_access = let is_cpp_container_read = @@ -608,6 +606,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct let astate = {astate with accesses} in let astate = match get_thread_model callee_pname with + | BackgroundThread + -> {astate with threads= ThreadsDomain.Background} | MainThread -> {astate with threads= ThreadsDomain.Main} | MainThreadIfTrue -> ( @@ -622,7 +622,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct -> L.(die InternalError) "Procedure %a specified as returning boolean, but returns nothing" Typ.Procname.pp callee_pname ) - | Unknown + | UnknownThread -> astate in let astate_callee = diff --git a/infer/tests/codetoanalyze/java/threadsafety/RaceWithMainThread.java b/infer/tests/codetoanalyze/java/threadsafety/RaceWithMainThread.java index 5fb2b67c7..a07dc97f7 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/RaceWithMainThread.java +++ b/infer/tests/codetoanalyze/java/threadsafety/RaceWithMainThread.java @@ -20,6 +20,7 @@ class OurThreadUtils{ class OurThreadUtil{ /*This is like AndroidThreadUtil*/ native static boolean isUiThread(); static void assertOnUiThread(){} + static void assertOnBackgroundThread(){} } @@ -186,4 +187,16 @@ class RaceWithMainThread{ } } + Object mFld; + + public void confusedAssertBad(boolean b) { + if (b) { + OurThreadUtil.assertOnBackgroundThread(); + } else { + OurThreadUtil.assertOnUiThread(); + } + // not sure if we're on UI or background, should report + mFld = null; + } + } diff --git a/infer/tests/codetoanalyze/java/threadsafety/issues.exp b/infer/tests/codetoanalyze/java/threadsafety/issues.exp index e12115794..fbbb9c1ef 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/issues.exp +++ b/infer/tests/codetoanalyze/java/threadsafety/issues.exp @@ -75,6 +75,7 @@ codetoanalyze/java/threadsafety/Ownership.java, void Ownership.writeToOwnedInCal codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional_isMainThread_ElseBranch_Bad(), 7, THREAD_SAFETY_VIOLATION, [access to `codetoanalyze.java.checkers.RaceWithMainThread.ff`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional_isMainThread_Negation_Bad(), 3, THREAD_SAFETY_VIOLATION, [access to `codetoanalyze.java.checkers.RaceWithMainThread.ff`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional_isUiThread_ElseBranch_Bad(), 7, THREAD_SAFETY_VIOLATION, [access to `codetoanalyze.java.checkers.RaceWithMainThread.ff`] +codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.confusedAssertBad(boolean), 7, THREAD_SAFETY_VIOLATION, [access to `codetoanalyze.java.checkers.RaceWithMainThread.mFld`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.readProtectedUnthreadedBad(), 3, THREAD_SAFETY_VIOLATION, [,access to `codetoanalyze.java.checkers.RaceWithMainThread.f`,,access to `codetoanalyze.java.checkers.RaceWithMainThread.f`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.read_unprotected_unthreaded1_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `codetoanalyze.java.checkers.RaceWithMainThread.f1`,,access to `codetoanalyze.java.checkers.RaceWithMainThread.f1`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.read_unprotected_unthreaded_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `codetoanalyze.java.checkers.RaceWithMainThread.f`,,access to `codetoanalyze.java.checkers.RaceWithMainThread.f`]