diff --git a/infer/src/backend/rearrange.ml b/infer/src/backend/rearrange.ml index 704324a46..572c1315f 100644 --- a/infer/src/backend/rearrange.ml +++ b/infer/src/backend/rearrange.ml @@ -744,6 +744,9 @@ let add_guarded_by_constraints tenv prop lexp pdesc = | Sil.Apred (Alocked, _) -> true | _ -> false) (Attribute.get_for_exp tenv prop guarded_by_exp) in + let guardedby_is_self_referential = + string_equal "itself" (String.lowercase guarded_by_str) || + string_is_suffix guarded_by_str (Ident.fieldname_to_string accessed_fld) in let should_warn pdesc = (* adding this check implements "by reference" semantics for guarded-by rather than "by value" semantics. if this access is through a local L or field V.f @@ -767,7 +770,8 @@ let add_guarded_by_constraints tenv prop lexp pdesc = Cfg.Procdesc.get_access pdesc <> PredSymb.Private && not (Annotations.pdesc_has_annot pdesc Annotations.visibleForTesting) && not (Procname.java_is_access_method (Cfg.Procdesc.get_proc_name pdesc)) && - not (is_accessible_through_local_ref lexp) in + not (is_accessible_through_local_ref lexp) && + not guardedby_is_self_referential in match find_guarded_by_exp guarded_by_str prop.Prop.sigma with | Some (Sil.Eexp (guarded_by_exp, _), typ) -> if is_read_write_lock typ diff --git a/infer/tests/codetoanalyze/java/infer/GuardedByExample.java b/infer/tests/codetoanalyze/java/infer/GuardedByExample.java index 920a7e902..8f92eed68 100644 --- a/infer/tests/codetoanalyze/java/infer/GuardedByExample.java +++ b/infer/tests/codetoanalyze/java/infer/GuardedByExample.java @@ -370,4 +370,36 @@ public class GuardedByExample { } } + @GuardedBy("self_reference") + Object self_reference; + + void guardedBySelfReferenceOK() { + synchronized(self_reference){ + this.self_reference.toString(); + } + } + + // TODO: report on this case, or at least a version which writes + /* + void guardedBySelfReferenceBad() { + this.self_reference.toString(); + } + */ + + @GuardedBy("itself") + Object itself_fld; + + void itselfOK() { + synchronized(itself_fld){ + this.itself_fld.toString(); + } + } + + // TODO: report on this case, or at least a version which writes + /* + void itselfBad() { + this.itself_fld.toString(); + } + */ + }