[starvation] catch calls to View.getVisibleDisplayFrame

Reviewed By: jeremydubreil

Differential Revision: D7758016

fbshipit-source-id: f3ff474
master
Nikos Gorogiannis 7 years ago committed by Facebook Github Bot
parent 6b37e61ec1
commit 63aafd3381

@ -542,40 +542,41 @@ module Models = struct
&& not (Annotations.pdesc_return_annot_ends_with proc_desc Annotations.visibleForTesting) && not (Annotations.pdesc_return_annot_ends_with proc_desc Annotations.visibleForTesting)
let is_blocking_java_io tenv pn = let is_call_of_class_or_superclass class_names ?(method_prefix= false) method_name tenv pn =
match pn with match pn with
| Typ.Procname.Java java_pname -> | Typ.Procname.Java java_pname ->
let classname = Typ.Procname.Java.get_class_type_name java_pname in let classname = Typ.Procname.Java.get_class_type_name java_pname in
let mthd = Typ.Procname.Java.get_method java_pname in let mthd = Typ.Procname.Java.get_method java_pname in
let is_reader_or_inputstream = let is_target_class =
let targets_str = ["java.io.Reader"; "java.io.InputStream"] in let targets = List.map class_names ~f:Typ.Name.Java.from_string in
let targets = List.map targets_str ~f:Typ.Name.Java.from_string in
fun tname _ -> List.mem targets tname ~equal:Typ.Name.equal fun tname _ -> List.mem targets tname ~equal:Typ.Name.equal
in in
String.is_prefix mthd ~prefix:"read" ( if method_prefix then String.is_prefix mthd ~prefix:method_name
&& PatternMatch.supertype_exists tenv is_reader_or_inputstream classname else String.equal mthd method_name )
&& PatternMatch.supertype_exists tenv is_target_class classname
| _ -> | _ ->
false false
let is_countdownlatch_await pn = let is_blocking_java_io =
match pn with let target_classes = ["java.io.Reader"; "java.io.InputStream"] in
| Typ.Procname.Java java_pname -> fun tenv pn -> is_call_of_class_or_superclass target_classes ~method_prefix:true "read" tenv pn
let classname = Typ.Procname.Java.get_class_name java_pname in
let mthd = Typ.Procname.Java.get_method java_pname in
String.equal classname "java.util.concurrent.CountDownLatch" && String.equal mthd "await"
| _ ->
false
let is_two_way_binder_transact tenv actuals pn = let is_countdownlatch_await =
match pn with let target_classes = ["java.util.concurrent.CountDownLatch"] in
| Typ.Procname.Java java_pname -> fun tenv pn -> is_call_of_class_or_superclass target_classes "await" tenv pn
let classname = Typ.Procname.Java.get_class_type_name java_pname in
let mthd = Typ.Procname.Java.get_method java_pname in
String.equal mthd "transact" let is_two_way_binder_transact =
&& PatternMatch.is_subtype_of_str tenv classname "android.os.IBinder" let target_classes = ["android.os.IBinder"] in
&& List.nth actuals 4 |> Option.value_map ~default:false ~f:HilExp.is_int_zero fun tenv actuals pn ->
| _ -> List.nth actuals 4 |> Option.value_map ~default:false ~f:HilExp.is_int_zero
false && is_call_of_class_or_superclass target_classes "transact" tenv pn
let is_getWindowVisibleDisplayFrame =
let target_classes = ["android.view.View"] in
fun tenv pn ->
is_call_of_class_or_superclass target_classes "getWindowVisibleDisplayFrame" tenv pn
end end

@ -86,12 +86,16 @@ module Models : sig
Initially, (Writer|OutputStream).(flush|close) were also matched, but this generated too Initially, (Writer|OutputStream).(flush|close) were also matched, but this generated too
many reports *) many reports *)
val is_countdownlatch_await : Typ.Procname.t -> bool val is_countdownlatch_await : Tenv.t -> Typ.Procname.t -> bool
(** is the method called CountDownLath.await? *) (** is the method called CountDownLath.await or on subclass? *)
val is_two_way_binder_transact : Tenv.t -> HilExp.t list -> Typ.Procname.t -> bool val is_two_way_binder_transact : Tenv.t -> HilExp.t list -> Typ.Procname.t -> bool
(* an IBinder.transact call is an RPC. If the 4th argument (5th counting `this` as the first) (* an IBinder.transact call is an RPC. If the 4th argument (5th counting `this` as the first)
is int-zero then a reply is expected and returned from the remote process, thus potentially is int-zero then a reply is expected and returned from the remote process, thus potentially
blocking. If the 4th argument is anything else, we assume a one-way call which doesn't block. blocking. If the 4th argument is anything else, we assume a one-way call which doesn't block.
*) *)
val is_getWindowVisibleDisplayFrame : Tenv.t -> Typ.Procname.t -> bool
(* is it a call to android.view.View.getWindowVisibleDisplayFrame or on sublass? *)
end end

@ -80,9 +80,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
astate astate
| NoEffect -> | NoEffect ->
if if
Models.is_countdownlatch_await callee Models.is_countdownlatch_await tenv callee
|| Models.is_two_way_binder_transact tenv actuals callee || Models.is_two_way_binder_transact tenv actuals callee
|| Models.is_blocking_java_io tenv callee || Models.is_blocking_java_io tenv callee
|| Models.is_getWindowVisibleDisplayFrame tenv callee
then then
let caller = Procdesc.get_proc_name pdesc in let caller = Procdesc.get_proc_name pdesc in
Domain.blocking_call ~caller ~callee loc astate Domain.blocking_call ~caller ~callee loc astate

@ -0,0 +1,26 @@
/*
* Copyright (c) 2018 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import android.view.View;
import android.graphics.Rect;
import android.support.annotation.UiThread;
class VisDispFrame {
View view;
Rect rect;
@UiThread
void callsGetVisibleDisplayFrameOnUiThreadBad() {
view.getWindowVisibleDisplayFrame(rect);
}
void callsGetVisibleDisplayFrameOk() {
view.getWindowVisibleDisplayFrame(rect);
}
}

@ -11,3 +11,4 @@ codetoanalyze/java/starvation/Intraproc.java, void IntraprocA.intraBad(Intraproc
codetoanalyze/java/starvation/JavaIO.java, void JavaIO.fileReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.fileReadBad(),Method call: int JavaIO.doFileRead(),calls int InputStreamReader.read() from int JavaIO.doFileRead()] codetoanalyze/java/starvation/JavaIO.java, void JavaIO.fileReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.fileReadBad(),Method call: int JavaIO.doFileRead(),calls int InputStreamReader.read() from int JavaIO.doFileRead()]
codetoanalyze/java/starvation/JavaIO.java, void JavaIO.streamReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.streamReadBad(),Method call: String JavaIO.doStreamRead(),calls String DataInputStream.readUTF() from String JavaIO.doStreamRead()] codetoanalyze/java/starvation/JavaIO.java, void JavaIO.streamReadBad(), 0, STARVATION, ERROR, [Method start: void JavaIO.streamReadBad(),Method call: String JavaIO.doStreamRead(),calls String DataInputStream.readUTF() from String JavaIO.doStreamRead()]
codetoanalyze/java/starvation/StaticLock.java, void StaticLock.lockOtherClassOneWayBad(), 0, STARVATION, ERROR, [[Trace 1] Method start: void StaticLock.lockOtherClassOneWayBad(),Locks StaticLock$0 in class java.lang.Class*,Locks this in class StaticLock*,[Trace 2] Locks this in class StaticLock*,Method call: void StaticLock.staticSynced(),Locks StaticLock$0 in class java.lang.Class*] codetoanalyze/java/starvation/StaticLock.java, void StaticLock.lockOtherClassOneWayBad(), 0, STARVATION, ERROR, [[Trace 1] Method start: void StaticLock.lockOtherClassOneWayBad(),Locks StaticLock$0 in class java.lang.Class*,Locks this in class StaticLock*,[Trace 2] Locks this in class StaticLock*,Method call: void StaticLock.staticSynced(),Locks StaticLock$0 in class java.lang.Class*]
codetoanalyze/java/starvation/VisDispFrame.java, void VisDispFrame.callsGetVisibleDisplayFrameOnUiThreadBad(), 0, STARVATION, ERROR, [Method start: void VisDispFrame.callsGetVisibleDisplayFrameOnUiThreadBad(),calls void View.getWindowVisibleDisplayFrame(Rect) from void VisDispFrame.callsGetVisibleDisplayFrameOnUiThreadBad()]

Loading…
Cancel
Save