diff --git a/infer/src/IR/Exceptions.ml b/infer/src/IR/Exceptions.ml index 69860b6fa..1935c4e22 100644 --- a/infer/src/IR/Exceptions.ml +++ b/infer/src/IR/Exceptions.ml @@ -65,8 +65,6 @@ exception Comparing_floats_for_equality of Localise.error_desc * L.ml_loc exception Condition_always_true_false of Localise.error_desc * bool * L.ml_loc -exception Context_leak of Localise.error_desc * L.ml_loc - exception Custom_error of string * Localise.error_desc exception Dangling_pointer_dereference of @@ -167,14 +165,6 @@ let recognize_exception exn = ; severity= Low ; kind= None ; category= Nocat } - | Context_leak (desc, _) -> - { name= IssueType.context_leak - ; description= desc - ; ml_loc= None - ; visibility= Exn_user - ; severity= High - ; kind= None - ; category= Nocat } | Analysis_stops (desc, ml_loc_opt) -> let visibility = if Config.analysis_stops then Exn_user else Exn_developer in { name= IssueType.analysis_stops diff --git a/infer/src/IR/Exceptions.mli b/infer/src/IR/Exceptions.mli index 7100ff0b1..752c3d57b 100644 --- a/infer/src/IR/Exceptions.mli +++ b/infer/src/IR/Exceptions.mli @@ -63,8 +63,6 @@ exception Comparing_floats_for_equality of Localise.error_desc * Logging.ml_loc exception Condition_always_true_false of Localise.error_desc * bool * Logging.ml_loc -exception Context_leak of Localise.error_desc * Logging.ml_loc - exception Custom_error of string * Localise.error_desc exception Dangling_pointer_dereference of diff --git a/infer/src/IR/Localise.ml b/infer/src/IR/Localise.ml index 280ff6bf5..ac672c582 100644 --- a/infer/src/IR/Localise.ml +++ b/infer/src/IR/Localise.ml @@ -434,44 +434,6 @@ let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc = ; "whenever " ^ pre_str ] } -let desc_context_leak pname context_typ fieldname leak_path : error_desc = - let fld_str = Typ.Fieldname.to_string fieldname in - let leak_root = "Static field " ^ fld_str ^ " |->\n" in - let leak_path_entry_to_str acc entry = - let entry_str = - match entry with - | Some fld, _ -> - Typ.Fieldname.to_string fld - | None, typ -> - Typ.to_string typ - in - (* intentionally omit space; [typ_to_string] adds an extra space *) - acc ^ entry_str ^ " |->\n" - in - let context_str = Typ.to_string context_typ in - let path_str = - let path_prefix = - if List.is_empty leak_path then "Leaked " - else List.fold ~f:leak_path_entry_to_str ~init:"" leak_path ^ "Leaked " - in - path_prefix ^ context_str - in - let preamble = - let pname_str = - match pname with - | Typ.Procname.Java pname_java -> - MF.monospaced_to_string - (Printf.sprintf "%s.%s" - (Typ.Procname.Java.get_class_name pname_java) - (Typ.Procname.Java.get_method pname_java)) - | _ -> - "" - in - "Context " ^ context_str ^ " may leak during method " ^ pname_str ^ ":\n" - in - {no_desc with descriptions= [preamble ^ MF.code_to_string (leak_root ^ path_str)]} - - let desc_double_lock pname_opt object_str loc = let mutex_str = Format.sprintf "Mutex %s" object_str in let tags = Tags.create () in diff --git a/infer/src/IR/Localise.mli b/infer/src/IR/Localise.mli index 49d997cad..0422c93a6 100644 --- a/infer/src/IR/Localise.mli +++ b/infer/src/IR/Localise.mli @@ -164,9 +164,6 @@ val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc val java_unchecked_exn_desc : Typ.Procname.t -> Typ.Name.t -> string -> error_desc -val desc_context_leak : - Typ.Procname.t -> Typ.t -> Typ.Fieldname.t -> (Typ.Fieldname.t option * Typ.t) list -> error_desc - val desc_fragment_retains_view : Typ.t -> Typ.Fieldname.t -> Typ.t -> Typ.Procname.t -> error_desc val desc_custom_error : Location.t -> error_desc diff --git a/infer/src/backend/errdesc.ml b/infer/src/backend/errdesc.ml index 28728cc6a..d7fda7cfb 100644 --- a/infer/src/backend/errdesc.ml +++ b/infer/src/backend/errdesc.ml @@ -63,11 +63,6 @@ let hpred_is_open_resource tenv prop = function None -(** Produce a description of a persistent reference to an Android Context *) -let explain_context_leak pname context_typ fieldname error_path = - Localise.desc_context_leak pname context_typ fieldname error_path - - (** Explain a deallocate stack variable error *) let explain_deallocate_stack_var pvar ra = let pvar_str = Pvar.to_string pvar in diff --git a/infer/src/backend/errdesc.mli b/infer/src/backend/errdesc.mli index 30ccbead4..5b6407232 100644 --- a/infer/src/backend/errdesc.mli +++ b/infer/src/backend/errdesc.mli @@ -38,11 +38,6 @@ val find_boolean_assignment : Procdesc.Node.t -> Pvar.t -> bool -> Procdesc.Node val exp_rv_dexp : Tenv.t -> Procdesc.Node.t -> Exp.t -> DecompiledExp.t option (** describe rvalue [e] as a dexp *) -val explain_context_leak : - Typ.Procname.t -> Typ.t -> Typ.Fieldname.t -> (Typ.Fieldname.t option * Typ.t) list - -> Localise.error_desc -(** Produce a description of a persistent reference to an Android Context *) - val explain_allocation_mismatch : PredSymb.res_action -> PredSymb.res_action -> Localise.error_desc (** Produce a description of a mismatch between an allocation function and a deallocation function *) diff --git a/infer/src/backend/interproc.ml b/infer/src/backend/interproc.ml index 1a4a9c170..6b0c3703b 100644 --- a/infer/src/backend/interproc.ml +++ b/infer/src/backend/interproc.ml @@ -514,93 +514,6 @@ let forward_tabulate tenv proc_cfg wl = L.d_ln () -(** if possible, produce a (fieldname, typ) path from one of the [src_exps] to [sink_exp] using - [reachable_hpreds]. *) -let get_fld_typ_path_opt src_exps sink_exp_ reachable_hpreds_ = - let strexp_matches target_exp = function - | Sil.Eexp (e, _) -> - Exp.equal target_exp e - | _ -> - false - in - let extend_path hpred (sink_exp, path, reachable_hpreds) = - match hpred with - | Sil.Hpointsto (lhs, Sil.Estruct (flds, _), Exp.Sizeof {typ}) -> - List.find ~f:(function _, se -> strexp_matches sink_exp se) flds - |> Option.value_map - ~f:(function - | fld, _ -> - let reachable_hpreds' = Sil.HpredSet.remove hpred reachable_hpreds in - (lhs, (Some fld, typ) :: path, reachable_hpreds')) - ~default:(sink_exp, path, reachable_hpreds) - | Sil.Hpointsto (lhs, Sil.Earray (_, elems, _), Exp.Sizeof {typ}) -> - if List.exists ~f:(function _, se -> strexp_matches sink_exp se) elems then - let reachable_hpreds' = Sil.HpredSet.remove hpred reachable_hpreds in - (* None means "no field name" ~=~ nameless array index *) - (lhs, (None, typ) :: path, reachable_hpreds') - else (sink_exp, path, reachable_hpreds) - | _ -> - (sink_exp, path, reachable_hpreds) - in - (* terminates because [reachable_hpreds] is shrinking on each recursive call *) - let rec get_fld_typ_path sink_exp path reachable_hpreds = - let sink_exp', path', reachable_hpreds' = - Sil.HpredSet.fold extend_path reachable_hpreds (sink_exp, path, reachable_hpreds) - in - if Exp.Set.mem sink_exp' src_exps then Some path' - else if Sil.HpredSet.cardinal reachable_hpreds' >= Sil.HpredSet.cardinal reachable_hpreds then - None (* can't find a path from [src_exps] to [sink_exp] *) - else get_fld_typ_path sink_exp' path' reachable_hpreds' - in - get_fld_typ_path sink_exp_ [] reachable_hpreds_ - - -(** report an error if any Context is reachable from a static field *) -let report_context_leaks pname sigma tenv = - (* report an error if an expression in [context_exps] is reachable from [field_strexp] *) - let check_reachable_context_from_fld (fld_name, fld_strexp) context_exps = - let fld_exps = Prop.strexp_get_exps fld_strexp in - let reachable_hpreds, reachable_exps = Prop.compute_reachable_hpreds sigma fld_exps in - (* raise an error if any Context expression is in [reachable_exps] *) - List.iter - ~f:(fun (context_exp, name) -> - if Exp.Set.mem context_exp reachable_exps then - match get_fld_typ_path_opt fld_exps context_exp reachable_hpreds with - | None -> - () (* TODO (T21871205): the underlying issue still need to be fixed *) - | Some leak_path -> - let err_desc = - Errdesc.explain_context_leak pname (Typ.mk (Tstruct name)) fld_name leak_path - in - let exn = Exceptions.Context_leak (err_desc, __POS__) in - Reporting.log_error_deprecated pname exn ) - context_exps - in - (* get the set of pointed-to expressions of type T <: Context *) - let context_exps = - List.fold - ~f:(fun exps hpred -> - match hpred with - | Sil.Hpointsto (_, Eexp (exp, _), Sizeof {typ= {desc= Tptr ({desc= Tstruct name}, _)}}) - when not (Exp.is_null_literal exp) && AndroidFramework.is_context tenv name - && not (AndroidFramework.is_application tenv name) -> - (exp, name) :: exps - | _ -> - exps ) - ~init:[] sigma - in - List.iter - ~f:(function - | Sil.Hpointsto (Exp.Lvar pv, Sil.Estruct (static_flds, _), _) when Pvar.is_global pv -> - List.iter - ~f:(fun (f_name, f_strexp) -> - check_reachable_context_from_fld (f_name, f_strexp) context_exps ) - static_flds - | _ -> - ()) - sigma - - (** Remove locals and formals, and check if the address of a stack variable is left in the result *) let remove_locals_formals_and_check tenv proc_cfg p = @@ -674,8 +587,6 @@ let extract_specs tenv pdesc pathset : Prop.normal Specs.spec list = let prop'' = Abs.abstract pname tenv prop' in let pre, post = Prop.extract_spec prop'' in let pre' = Prop.normalize tenv (Prop.prop_sub (`Exp sub) pre) in - if Language.curr_language_is Java && Procdesc.get_access pdesc <> PredSymb.Private then - report_context_leaks pname post.Prop.sigma tenv ; let post' = if Prover.check_inconsistency_base tenv prop then None else Some (Prop.normalize tenv (Prop.prop_sub (`Exp sub) post), path) diff --git a/infer/src/backend/prop.ml b/infer/src/backend/prop.ml index 1fcf2a519..fd71e8995 100644 --- a/infer/src/backend/prop.ml +++ b/infer/src/backend/prop.ml @@ -588,54 +588,6 @@ let prop_sigma_star (p: 'a t) (sigma: sigma) : exposed t = set p ~sigma:sigma' -(** return the set of subexpressions of [strexp] *) -let strexp_get_exps strexp = - let rec strexp_get_exps_rec exps (se: Sil.strexp) = - match se with - | Eexp (Exn e, _) -> - Exp.Set.add e exps - | Eexp (e, _) -> - Exp.Set.add e exps - | Estruct (flds, _) -> - List.fold ~f:(fun exps (_, strexp) -> strexp_get_exps_rec exps strexp) ~init:exps flds - | Earray (_, elems, _) -> - List.fold ~f:(fun exps (_, strexp) -> strexp_get_exps_rec exps strexp) ~init:exps elems - in - strexp_get_exps_rec Exp.Set.empty strexp - - -(** get the set of expressions on the righthand side of [hpred] *) -let hpred_get_targets (hpred: Sil.hpred) = - match hpred with - | Hpointsto (_, rhs, _) -> - strexp_get_exps rhs - | Hlseg (_, _, _, e, el) -> - List.fold ~f:(fun exps e -> Exp.Set.add e exps) ~init:Exp.Set.empty (e :: el) - | Hdllseg (_, _, _, oB, oF, iB, el) -> - (* only one direction supported for now *) - List.fold ~f:(fun exps e -> Exp.Set.add e exps) ~init:Exp.Set.empty (oB :: oF :: iB :: el) - - -(** return the set of hpred's and exp's in [sigma] that are reachable from an expression in - [exps] *) -let compute_reachable_hpreds sigma exps = - let rec compute_reachable_hpreds_rec sigma (reach, exps) = - let add_hpred_if_reachable (reach, exps) (hpred: Sil.hpred) = - match hpred with - | Hpointsto (lhs, _, _) as hpred when Exp.Set.mem lhs exps -> - let reach' = Sil.HpredSet.add hpred reach in - let reach_exps = hpred_get_targets hpred in - (reach', Exp.Set.union exps reach_exps) - | _ -> - (reach, exps) - in - let reach', exps' = List.fold ~f:add_hpred_if_reachable ~init:(reach, exps) sigma in - if Int.equal (Sil.HpredSet.cardinal reach) (Sil.HpredSet.cardinal reach') then (reach, exps) - else compute_reachable_hpreds_rec sigma (reach', exps') - in - compute_reachable_hpreds_rec sigma (Sil.HpredSet.empty, exps) - - (* Module for normalization *) module Normalize = struct (** Eliminates all empty lsegs from sigma, and collect equalities @@ -1416,8 +1368,8 @@ module Normalize = struct (** Captured variables in the closures consist of expressions and variables, with the implicit - assumption that these two values are in the relation &var -> id. However, after bi-abduction, etc. - the constraint may not hold anymore, so this function ensures that it is always kept. + assumption that these two values are in the relation &var -> id. However, after bi-abduction, etc. + the constraint may not hold anymore, so this function ensures that it is always kept. In particular, we have &var -> id iff we also have the pair (id, var) as part of captured variables. *) let make_captured_in_closures_consistent sigma = let open Sil in diff --git a/infer/src/backend/prop.mli b/infer/src/backend/prop.mli index f775b1af9..43d20a53c 100644 --- a/infer/src/backend/prop.mli +++ b/infer/src/backend/prop.mli @@ -350,13 +350,6 @@ val prop_iter_make_id_primed : Tenv.t -> Ident.t -> 'a prop_iter -> 'a prop_iter val prop_iter_gc_fields : unit prop_iter -> unit prop_iter (** Collect garbage fields. *) -val strexp_get_exps : Sil.strexp -> Exp.Set.t -(** return the set of subexpressions of [strexp] *) - -val compute_reachable_hpreds : hpred list -> Exp.Set.t -> Sil.HpredSet.t * Exp.Set.t -(** return the set of hpred's and exp's in [sigma] that are reachable from an expression in - [exps] *) - (** {2 Internal modules} *) module Metrics : sig diff --git a/infer/src/base/IssueType.ml b/infer/src/base/IssueType.ml index e2e9b8c85..6ce214f25 100644 --- a/infer/src/base/IssueType.ml +++ b/infer/src/base/IssueType.ml @@ -132,8 +132,6 @@ let condition_always_false = from_string ~enabled:false "CONDITION_ALWAYS_FALSE" let condition_always_true = from_string ~enabled:false "CONDITION_ALWAYS_TRUE" -let context_leak = from_string "CONTEXT_LEAK" - let create_intent_from_uri = from_string "CREATE_INTENT_FROM_URI" let cross_site_scripting = from_string "CROSS_SITE_SCRIPTING" diff --git a/infer/src/base/IssueType.mli b/infer/src/base/IssueType.mli index fdde249bb..3e82a15dc 100644 --- a/infer/src/base/IssueType.mli +++ b/infer/src/base/IssueType.mli @@ -87,8 +87,6 @@ val condition_always_false : t val condition_always_true : t -val context_leak : t - val create_intent_from_uri : t val cross_site_scripting : t diff --git a/infer/src/base/MarkupFormatter.ml b/infer/src/base/MarkupFormatter.ml index 2f4af84dd..fa1b64e07 100644 --- a/infer/src/base/MarkupFormatter.ml +++ b/infer/src/base/MarkupFormatter.ml @@ -15,7 +15,6 @@ type 'a formatter = ; monospaced_to_string: string -> string ; wrap_code: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a -> unit ; pp_code: Format.formatter -> string -> unit - ; code_to_string: string -> string ; wrap_bold: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a -> unit ; pp_bold: Format.formatter -> string -> unit ; bold_to_string: string -> string } @@ -33,7 +32,6 @@ end = struct ; monospaced_to_string= Fn.id ; wrap_code= wrap_simple ; pp_code= pp_simple - ; code_to_string= Fn.id ; wrap_bold= wrap_simple ; pp_bold= pp_simple ; bold_to_string= Fn.id } @@ -53,8 +51,6 @@ end = struct let pp_code fmt s = wrap_code Format.pp_print_string fmt s - let code_to_string s = Format.asprintf "%a" pp_code s - let wrap_bold pp fmt x = Format.fprintf fmt "**%a**" pp x let pp_bold fmt s = wrap_bold Format.pp_print_string fmt s @@ -67,7 +63,6 @@ end = struct ; monospaced_to_string ; wrap_code ; pp_code - ; code_to_string ; wrap_bold ; pp_bold ; bold_to_string } @@ -91,8 +86,6 @@ let wrap_code = formatter.wrap_code let pp_code = formatter.pp_code -let code_to_string = formatter.code_to_string - let wrap_bold = formatter.wrap_bold let pp_bold = formatter.pp_bold diff --git a/infer/src/base/MarkupFormatter.mli b/infer/src/base/MarkupFormatter.mli index 2a19da98b..f504dbdd7 100644 --- a/infer/src/base/MarkupFormatter.mli +++ b/infer/src/base/MarkupFormatter.mli @@ -26,9 +26,6 @@ val pp_code : Format.formatter -> string -> unit [@@warning "-32"] (** pp to wrap into a code block *) -val code_to_string : string -> string -(** wrap into a code block *) - val wrap_bold : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a -> unit [@@warning "-32"] (** used to combine pp together, wrap content into a bold block *) diff --git a/infer/src/checkers/androidFramework.ml b/infer/src/checkers/androidFramework.ml index 155c816a1..021894740 100644 --- a/infer/src/checkers/androidFramework.ml +++ b/infer/src/checkers/androidFramework.ml @@ -35,10 +35,6 @@ let is_subtype_package_class tenv tname package classname = let is_autocloseable tenv tname = is_subtype_package_class tenv tname "java.lang" "AutoCloseable" -let is_context tenv tname = is_subtype_package_class tenv tname "android.content" "Context" - -let is_application tenv tname = is_subtype_package_class tenv tname "android.app" "Application" - let is_view tenv tname = is_subtype_package_class tenv tname "android.view" "View" let is_fragment tenv tname = diff --git a/infer/src/checkers/androidFramework.mli b/infer/src/checkers/androidFramework.mli index 79c76141e..11b0d4e24 100644 --- a/infer/src/checkers/androidFramework.mli +++ b/infer/src/checkers/androidFramework.mli @@ -16,12 +16,6 @@ val drawable_prefix : string val is_autocloseable : Tenv.t -> Typ.Name.t -> bool -val is_context : Tenv.t -> Typ.Name.t -> bool -(** return true if [typename] <: android.content.Context *) - -val is_application : Tenv.t -> Typ.Name.t -> bool -(** return true if [typename] <: android.app.Application *) - val is_view : Tenv.t -> Typ.Name.t -> bool (** return true if [typename] <: android.view.View *) diff --git a/infer/tests/build_systems/ant/issues.exp b/infer/tests/build_systems/ant/issues.exp index 1fbd78d0d..fbffcec43 100644 --- a/infer/tests/build_systems/ant/issues.exp +++ b/infer/tests/build_systems/ant/issues.exp @@ -11,12 +11,6 @@ codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResour codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResourceExample.notClosingWrapper(), 2, RESOURCE_LEAK, [start of procedure notClosingWrapper(),start of procedure Resource(),return from a call to Resource.(),start of procedure Sub(...),start of procedure Wrapper(...),return from a call to Wrapper.(Resource),return from a call to Sub.(Resource),start of procedure close(),return from a call to void Resource.close()] codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResourceExample.skippedVritualCallDoesNotCloseResourceOnReceiver(), 2, RESOURCE_LEAK, [start of procedure skippedVritualCallDoesNotCloseResourceOnReceiver(),start of procedure SomeResource(),return from a call to SomeResource.(),Skipping foo(...): method has no implementation,Definition of foo(...)] codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResourceExample.withException(), 4, RESOURCE_LEAK, [start of procedure withException(),start of procedure SomeResource(),return from a call to SomeResource.(),start of procedure doSomething(),Skipping star(): method has no implementation,Definition of star(),Taking true branch,start of procedure LocalException(),return from a call to LocalException.(),exception codetoanalyze.java.infer.LocalException,return from a call to void SomeResource.doSomething()] -codetoanalyze/java/infer/ContextLeaks.java, ContextLeaks$Singleton ContextLeaks$Singleton.getInstance(Context), 4, CONTEXT_LEAK, [start of procedure getInstance(...),Taking false branch,return from a call to ContextLeaks$Singleton ContextLeaks$Singleton.getInstance(Context)] -codetoanalyze/java/infer/ContextLeaks.java, ContextLeaks$Singleton ContextLeaks.singletonLeak(), 1, CONTEXT_LEAK, [start of procedure singletonLeak(),start of procedure getInstance(...),Taking false branch,return from a call to ContextLeaks$Singleton ContextLeaks$Singleton.getInstance(Context),return from a call to ContextLeaks$Singleton ContextLeaks.singletonLeak()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.directLeak(), 2, CONTEXT_LEAK, [start of procedure directLeak(),return from a call to void ContextLeaks.directLeak()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.indirectLeak(), 4, CONTEXT_LEAK, [start of procedure indirectLeak(),start of procedure ContextLeaks$Obj(),return from a call to ContextLeaks$Obj.(),return from a call to void ContextLeaks.indirectLeak()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.leakAfterInstanceFieldWrite(), 3, CONTEXT_LEAK, [start of procedure leakAfterInstanceFieldWrite(),return from a call to void ContextLeaks.leakAfterInstanceFieldWrite()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.nonStaticInnerClassLeak(), 2, CONTEXT_LEAK, [start of procedure nonStaticInnerClassLeak(),start of procedure ContextLeaks$NonStaticInner(...),return from a call to ContextLeaks$NonStaticInner.(ContextLeaks),return from a call to void ContextLeaks.nonStaticInnerClassLeak()] codetoanalyze/java/infer/CursorLeaks.java, Object CursorLeaks.cursorClosedCheckNullCheckClosed_FP(SQLiteDatabase), 13, RESOURCE_LEAK, [start of procedure cursorClosedCheckNullCheckClosed_FP(...),Taking false branch,Skipping getString(...): unknown method,Taking true branch,Taking false branch] codetoanalyze/java/infer/CursorLeaks.java, int CursorLeaks.completeDownloadNotClosed(DownloadManager), 8, RESOURCE_LEAK, [start of procedure completeDownloadNotClosed(...),Taking false branch,Skipping getColumnIndex(...): unknown method] codetoanalyze/java/infer/CursorLeaks.java, int CursorLeaks.cursorNotClosed(SQLiteDatabase), 4, RESOURCE_LEAK, [start of procedure cursorNotClosed(...),Skipping getCount(): unknown method] diff --git a/infer/tests/codetoanalyze/java/infer/ContextLeaks.java b/infer/tests/codetoanalyze/java/infer/ContextLeaks.java deleted file mode 100644 index bce42a31f..000000000 --- a/infer/tests/codetoanalyze/java/infer/ContextLeaks.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2015 - 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. - */ - -package codetoanalyze.java.infer; - -import java.lang.ref.WeakReference; - -import android.content.Context; -import android.app.Activity; - -public class ContextLeaks extends Activity { - - static Object sFld; - - void directLeak() { - sFld = this; - } - - public void leakThenFix() { - sFld = this; - sFld = null; - } - - public void nonActivityNoLeak() { - sFld = new Object(); - } - - static class Obj { - public Object f; - } - - public void indirectLeak() { - Obj o = new Obj(); - o.f = this; - sFld = o; - } - - public void indirectLeakThenFix() { - Obj o = new Obj(); - o.f = this; - sFld = o; - o.f = null; - } - - class NonStaticInner { - } - - public void nonStaticInnerClassLeak() { - sFld = new NonStaticInner(); - } - - public void nonStaticInnerClassLeakThenFix() { - sFld = new NonStaticInner(); - sFld = null; - } - - private Object o; - - public void leakAfterInstanceFieldWrite() { - this.o = new Object(); - sFld = this; - } - - public static class Singleton { - - private static Singleton instance; - private Context context; - - private Singleton(Context context) { - this.context = context; - } - - public static Singleton getInstance(Context context) { - if (instance == null) { - instance = new Singleton(context); - } - return instance; - } - } - - public Singleton singletonLeak() { - return Singleton.getInstance(this); - } - - public Singleton singletonNoLeak() { - return Singleton.getInstance(this.getApplicationContext()); - } - - // testing that we don't report on static field -> ... -> Context paths broken by weak refs - static WeakReference sDirectWeakReference; - - static WeakReference sIndirectWeakReference1; - - static Obj sIndirectWeakReference2; - - // sDirectWeakReference |-> WeakReference.referent |-> Context - public void directWeakReferenceOk() { - sDirectWeakReference = new WeakReference(this); - } - - // sIndirectWeakReference1 |-> WeakReference.referent |-> Obj.f |-> Context - public void indirectWeakReferenceOk1() { - Obj obj = new Obj(); - obj.f = this; - sIndirectWeakReference1 = new WeakReference(obj); - } - - // sIndirectWeakReference2.|-> Obj.f |-> WeakReference.referent |-> Context - public void indirectWeakReferenceOk2() { - Obj obj = new Obj(); - obj.f = new WeakReference(this); - sIndirectWeakReference2 = obj; - } - -} diff --git a/infer/tests/codetoanalyze/java/infer/issues.exp b/infer/tests/codetoanalyze/java/infer/issues.exp index f7a3fa741..2227ec935 100644 --- a/infer/tests/codetoanalyze/java/infer/issues.exp +++ b/infer/tests/codetoanalyze/java/infer/issues.exp @@ -30,12 +30,6 @@ codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResour codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResourceExample.notClosingWrapper(), 2, RESOURCE_LEAK, [start of procedure notClosingWrapper(),start of procedure Resource(),return from a call to Resource.(),start of procedure Sub(...),start of procedure Wrapper(...),return from a call to Wrapper.(Resource),return from a call to Sub.(Resource),start of procedure close(),return from a call to void Resource.close()] codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResourceExample.skippedVritualCallDoesNotCloseResourceOnReceiver(), 2, RESOURCE_LEAK, [start of procedure skippedVritualCallDoesNotCloseResourceOnReceiver(),start of procedure SomeResource(),return from a call to SomeResource.(),Skipping foo(...): method has no implementation,Definition of foo(...)] codetoanalyze/java/infer/CloseableAsResourceExample.java, void CloseableAsResourceExample.withException(), 4, RESOURCE_LEAK, [start of procedure withException(),start of procedure SomeResource(),return from a call to SomeResource.(),start of procedure doSomething(),Skipping star(): method has no implementation,Definition of star(),Taking true branch,start of procedure LocalException(),return from a call to LocalException.(),exception codetoanalyze.java.infer.LocalException,return from a call to void SomeResource.doSomething()] -codetoanalyze/java/infer/ContextLeaks.java, ContextLeaks$Singleton ContextLeaks$Singleton.getInstance(Context), 4, CONTEXT_LEAK, [start of procedure getInstance(...),Taking false branch,return from a call to ContextLeaks$Singleton ContextLeaks$Singleton.getInstance(Context)] -codetoanalyze/java/infer/ContextLeaks.java, ContextLeaks$Singleton ContextLeaks.singletonLeak(), 1, CONTEXT_LEAK, [start of procedure singletonLeak(),start of procedure getInstance(...),Taking false branch,return from a call to ContextLeaks$Singleton ContextLeaks$Singleton.getInstance(Context),return from a call to ContextLeaks$Singleton ContextLeaks.singletonLeak()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.directLeak(), 2, CONTEXT_LEAK, [start of procedure directLeak(),return from a call to void ContextLeaks.directLeak()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.indirectLeak(), 4, CONTEXT_LEAK, [start of procedure indirectLeak(),start of procedure ContextLeaks$Obj(),return from a call to ContextLeaks$Obj.(),return from a call to void ContextLeaks.indirectLeak()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.leakAfterInstanceFieldWrite(), 3, CONTEXT_LEAK, [start of procedure leakAfterInstanceFieldWrite(),return from a call to void ContextLeaks.leakAfterInstanceFieldWrite()] -codetoanalyze/java/infer/ContextLeaks.java, void ContextLeaks.nonStaticInnerClassLeak(), 2, CONTEXT_LEAK, [start of procedure nonStaticInnerClassLeak(),start of procedure ContextLeaks$NonStaticInner(...),return from a call to ContextLeaks$NonStaticInner.(ContextLeaks),return from a call to void ContextLeaks.nonStaticInnerClassLeak()] codetoanalyze/java/infer/CursorLeaks.java, Object CursorLeaks.cursorClosedCheckNullCheckClosed_FP(SQLiteDatabase), 13, RESOURCE_LEAK, [start of procedure cursorClosedCheckNullCheckClosed_FP(...),Taking false branch,Skipping getString(...): unknown method,Taking true branch,Taking false branch] codetoanalyze/java/infer/CursorLeaks.java, int CursorLeaks.completeDownloadNotClosed(DownloadManager), 8, RESOURCE_LEAK, [start of procedure completeDownloadNotClosed(...),Taking false branch,Skipping getColumnIndex(...): unknown method] codetoanalyze/java/infer/CursorLeaks.java, int CursorLeaks.cursorNotClosed(SQLiteDatabase), 4, RESOURCE_LEAK, [start of procedure cursorNotClosed(...),Skipping getCount(): unknown method]