diff --git a/infer/src/concurrency/StarvationModels.ml b/infer/src/concurrency/StarvationModels.ml index dfd9a5345..56c43c06e 100644 --- a/infer/src/concurrency/StarvationModels.ml +++ b/infer/src/concurrency/StarvationModels.ml @@ -238,7 +238,13 @@ let schedules_work_on_ui_thread = let matcher = [ { default with classname= "java.lang.Object" - ; methods= ["postOnUiThread"; "runOnUiThread"; "postOnUiThreadDelayed"] } ] + ; methods= + [ "postOnUiThread" + ; "postOnUiThreadDelayed" + ; "postToUiThread" + ; "runOnUiThread" + ; "runOnUiThreadAsync" + ; "runOnUiThreadAsyncWithDelay" ] } ] |> of_records in fun tenv pname -> matcher tenv pname [] @@ -316,6 +322,8 @@ let get_returned_executor ~attrs_of_pname tenv callee actuals = match Typ.Procname.Java.get_method java_pname with | ("getForegroundExecutor" | "getBackgroundExecutor") when Lazy.force type_check -> Some ForNonUIThread + | "getUiThreadExecutorService" when Lazy.force type_check -> + Some ForUIThread | _ -> None ) | _ -> @@ -324,26 +332,26 @@ let get_returned_executor ~attrs_of_pname tenv callee actuals = let is_getMainLooper = let open MethodMatcher in - [ { default with + of_record + { default with classname= "android.os.Looper" ; methods= ["getMainLooper"] - ; actuals_pred= List.is_empty } ] - |> of_records + ; actuals_pred= List.is_empty } let is_handler_constructor = let open MethodMatcher in - [ { default with + of_record + { default with classname= "android.os.Handler" ; methods= [Typ.Procname.Java.constructor_method_name] - ; actuals_pred= (fun actuals -> not (List.is_empty actuals)) } ] - |> of_records + ; actuals_pred= (fun actuals -> not (List.is_empty actuals)) } let is_thread_constructor = let open MethodMatcher in - [ { default with + of_record + { default with classname= "java.lang.Thread" ; search_superclasses= false - ; methods= [Typ.Procname.Java.constructor_method_name] } ] - |> of_records + ; methods= [Typ.Procname.Java.constructor_method_name] } diff --git a/infer/tests/codetoanalyze/java/starvation-whole-program/Executors.java b/infer/tests/codetoanalyze/java/starvation-whole-program/Executors.java index eaf431b16..f52162d9a 100644 --- a/infer/tests/codetoanalyze/java/starvation-whole-program/Executors.java +++ b/infer/tests/codetoanalyze/java/starvation-whole-program/Executors.java @@ -23,6 +23,8 @@ class Executors { public static void postOnUiThread(Runnable runnable) {} + public static void postToUiThread(Runnable runnable) {} + public static void runOnUiThread(Runnable runnable) {} public static void postOnUiThreadDelayed(Runnable runnable, long delayMs) {} diff --git a/infer/tests/codetoanalyze/java/starvation-whole-program/ModeledExecutors.java b/infer/tests/codetoanalyze/java/starvation-whole-program/ModeledExecutors.java index 91430423d..1ea765b14 100644 --- a/infer/tests/codetoanalyze/java/starvation-whole-program/ModeledExecutors.java +++ b/infer/tests/codetoanalyze/java/starvation-whole-program/ModeledExecutors.java @@ -160,4 +160,14 @@ class ModeledExecutors { } }); } + + public void postToUIThreadBad() { + Executors.postToUiThread( + new Runnable() { + @Override + public void run() { + doTransact(); + } + }); + } } diff --git a/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp b/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp index 82b71b2b0..c328b40ac 100644 --- a/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp +++ b/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp @@ -11,6 +11,7 @@ codetoanalyze/java/starvation-whole-program/DirectStarvation.java, DirectStarvat codetoanalyze/java/starvation-whole-program/ImplicitConstructor.java, ImplicitConstructor.postBlockingCallToUIExecutorBad():void, 54, STARVATION, no_bucket, ERROR, [`void ImplicitConstructor.postBlockingCallToUIExecutorBad()`,Method call: `void ImplicitConstructor$1.run()`,Method call: `void ImplicitConstructor.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ImplicitConstructor.java, ImplicitConstructor.postBlockingCallToUIHandlerBad():void, 66, STARVATION, no_bucket, ERROR, [`void ImplicitConstructor.postBlockingCallToUIHandlerBad()`,Method call: `void ImplicitConstructor$1.run()`,Method call: `void ImplicitConstructor.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/IndirectStarvation.java, IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad():void, 32, STARVATION, no_bucket, ERROR, [[Trace 1] `void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$1.run()`, locks `this.monitorA` in `class IndirectStarvation`,[Trace 2] `void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$2.run()`, locks `this.monitorA` in `class IndirectStarvation`,Method call: `void IndirectStarvation.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.postToUIThreadBad():void, 165, STARVATION, no_bucket, ERROR, [`void ModeledExecutors.postToUIThreadBad()`,Method call: `void ModeledExecutors$12.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleBlockingCallToUIThreadBad():void, 140, STARVATION, no_bucket, ERROR, [`void ModeledExecutors.scheduleBlockingCallToUIThreadBad()`,Method call: `void ModeledExecutors$10.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad():void, 97, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$7.run()`, locks `this.monitorA` in `class ModeledExecutors`, locks `this.monitorB` in `class ModeledExecutors`,[Trace 2] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$8.run()`, locks `this.monitorB` in `class ModeledExecutors`, locks `this.monitorA` in `class ModeledExecutors`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad():void, 110, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$8.run()`, locks `this.monitorB` in `class ModeledExecutors`, locks `this.monitorA` in `class ModeledExecutors`,[Trace 2] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$7.run()`, locks `this.monitorA` in `class ModeledExecutors`, locks `this.monitorB` in `class ModeledExecutors`]