diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index a7f947561..7c5939b2f 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -1202,7 +1202,14 @@ let trace_of_pname orig_sink orig_pdesc callee_pname = | _ -> PathDomain.empty -let make_trace_with_conflicts conflicts original_path pdesc = +type conflicts = ThreadSafetyDomain.TraceElem.t list + +type report_kind = + | WriteWriteRace of conflicts (** possibly-empty list of conflicting accesses *) + | ReadWriteRace of conflicts (** non-empty list of conflicting accesses *) + | UnannotatedInterface + +let make_trace ~report_kind original_path pdesc = let open ThreadSafetyDomain in let loc_trace_of_path path = PathDomain.to_sink_loc_trace ~desc_of_sink path in let make_trace_for_sink sink = @@ -1214,22 +1221,30 @@ let make_trace_with_conflicts conflicts original_path pdesc = -> [] in let original_trace = loc_trace_of_path original_path in - match conflicts with - | conflict_sink :: _ - -> (* create a trace for one of the conflicts and append it to the trace for the original sink *) - let conflict_trace = make_trace_for_sink conflict_sink in - let get_start_loc = function head :: _ -> head.Errlog.lt_loc | [] -> Location.dummy in - let first_trace_spacer = - Errlog.make_trace_element 0 (get_start_loc original_trace) "" [] - in - let second_trace_spacer = - Errlog.make_trace_element 0 (get_start_loc conflict_trace) "" [] - in - first_trace_spacer :: original_trace @ second_trace_spacer :: conflict_trace - | [] + let make_with_conflicts conflict_sink original_trace ~label1 ~label2 = + (* create a trace for one of the conflicts and append it to the trace for the original sink *) + let conflict_trace = make_trace_for_sink conflict_sink in + let get_start_loc = function head :: _ -> head.Errlog.lt_loc | [] -> Location.dummy in + let first_trace_spacer = + Errlog.make_trace_element 0 (get_start_loc original_trace) label1 [] + in + let second_trace_spacer = + Errlog.make_trace_element 0 (get_start_loc conflict_trace) label2 [] + in + first_trace_spacer :: original_trace @ second_trace_spacer :: conflict_trace + in + match report_kind with + | ReadWriteRace (conflict_sink :: _) + -> make_with_conflicts conflict_sink original_trace ~label1:"" + ~label2:"" + | WriteWriteRace (conflict_sink :: _) + -> make_with_conflicts conflict_sink original_trace ~label1:"" + ~label2:"" + | ReadWriteRace [] | WriteWriteRace [] | UnannotatedInterface -> original_trace -let report_thread_safety_violation tenv pdesc issue_type ~make_description ~conflicts access thread = +let report_thread_safety_violation tenv pdesc issue_type ~make_description ~report_kind access + thread = let open ThreadSafetyDomain in let pname = Procdesc.get_proc_name pdesc in let report_one_path (_, sinks as path) = @@ -1238,7 +1253,7 @@ let report_thread_safety_violation tenv pdesc issue_type ~make_description ~conf let initial_sink_site = PathDomain.Sink.call_site initial_sink in let final_sink_site = PathDomain.Sink.call_site final_sink in let loc = CallSite.loc initial_sink_site in - let ltr = make_trace_with_conflicts conflicts path pdesc in + let ltr = make_trace ~report_kind path pdesc in let description = make_description tenv pname final_sink_site initial_sink_site final_sink thread in @@ -1260,7 +1275,7 @@ let report_unannotated_interface_violation tenv pdesc access thread reported_pna class_name MF.pp_monospaced "@ThreadSafe" in report_thread_safety_violation tenv pdesc IssueType.interface_not_thread_safe - ~make_description ~conflicts:[] access thread + ~make_description ~report_kind:UnannotatedInterface access thread | _ -> (* skip reporting on C++ *) () @@ -1411,11 +1426,24 @@ let report_unsafe_accesses , (AccessPrecondition.Unprotected _ | AccessPrecondition.TotallyUnprotected) ) -> ( match Procdesc.get_proc_name pdesc with | Java _ - -> (** TODO: use a better warning message when the thread is anything but Any (perhaps - show the write that this may race with) *) - (* unprotected write. warn. *) + -> let writes_on_background_thread = + if ThreadsDomain.is_any thread then + (* unprotected write in method that may run in parallel with itself. warn *) + [] + else + (* unprotected write, but not on a method that may run in parallel with itself + (i.e., not a self race). find accesses on a background thread this access might + conflict with and report them *) + List.filter_map + ~f:(fun (other_access, _, other_thread, _, _) -> + if TraceElem.is_write other_access && ThreadsDomain.is_any other_thread then + Some other_access + else None) + accesses + in report_thread_safety_violation tenv pdesc IssueType.thread_safety_violation - ~make_description:make_unprotected_write_description ~conflicts:[] access thread ; + ~make_description:make_unprotected_write_description + ~report_kind:(WriteWriteRace writes_on_background_thread) access thread ; update_reported access pname reported_acc | _ -> (* Do not report unprotected writes when an access can't run in parallel with itself, or @@ -1448,7 +1476,8 @@ let report_unsafe_accesses else ( report_thread_safety_violation tenv pdesc IssueType.thread_safety_violation ~make_description:(make_read_write_race_description ~read_is_sync:false all_writes) - ~conflicts:(List.map ~f:(fun (access, _, _, _, _) -> access) all_writes) + ~report_kind: + (ReadWriteRace (List.map ~f:(fun (access, _, _, _, _) -> access) all_writes)) access thread ; update_reported access pname reported_acc ) | (Access.Read _ | ContainerRead _), AccessPrecondition.Protected excl @@ -1480,7 +1509,9 @@ let report_unsafe_accesses report_thread_safety_violation tenv pdesc IssueType.thread_safety_violation ~make_description: (make_read_write_race_description ~read_is_sync:true conflicting_writes) - ~conflicts:(List.map ~f:(fun (access, _, _, _, _) -> access) conflicting_writes) + ~report_kind: + (ReadWriteRace + (List.map ~f:(fun (access, _, _, _, _) -> access) conflicting_writes)) access thread ; update_reported access pname reported_acc ) in diff --git a/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp b/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp index 48b98c45b..369f550cb 100644 --- a/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp +++ b/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp @@ -1,12 +1,12 @@ -codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written`,,access to `&this.suspiciously_written`] -codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] -codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get5, 0, THREAD_SAFETY_VIOLATION, [,call to basics::Basic_get_private_suspiciously_read,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] -codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written`,,access to `&this.suspiciously_written`] -codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] -codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_test1, 2, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] -codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp, basics::LockGuardWithScope_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written`,,access to `&this.suspiciously_written`] -codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp, basics::LockGuardWithScope_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] -codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written1`,,access to `&this.suspiciously_written1`] -codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get2, 4, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written2`,,access to `&this.suspiciously_written2`] -codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get4, 1, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read1`,,access to `&this.suspiciously_read1`] -codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get4, 2, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read2`,,access to `&this.suspiciously_read2`] +codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written`,,access to `&this.suspiciously_written`] +codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] +codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get5, 0, THREAD_SAFETY_VIOLATION, [,call to basics::Basic_get_private_suspiciously_read,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] +codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written`,,access to `&this.suspiciously_written`] +codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] +codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_test1, 2, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] +codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp, basics::LockGuardWithScope_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written`,,access to `&this.suspiciously_written`] +codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp, basics::LockGuardWithScope_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read`,,access to `&this.suspiciously_read`] +codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written1`,,access to `&this.suspiciously_written1`] +codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get2, 4, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_written2`,,access to `&this.suspiciously_written2`] +codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get4, 1, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read1`,,access to `&this.suspiciously_read1`] +codetoanalyze/cpp/threadsafety/unique_lock.cpp, basics::UniqueLock_get4, 2, THREAD_SAFETY_VIOLATION, [,access to `&this.suspiciously_read2`,,access to `&this.suspiciously_read2`] diff --git a/infer/tests/codetoanalyze/java/threadsafety/ThreadSafeMethods.java b/infer/tests/codetoanalyze/java/threadsafety/ThreadSafeMethods.java index 24b10ab95..be1b29969 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/ThreadSafeMethods.java +++ b/infer/tests/codetoanalyze/java/threadsafety/ThreadSafeMethods.java @@ -46,9 +46,10 @@ class ThreadSafeMethods { public void safeMethodOverride() { } - // won't report this now, but should in the future. if a method annotated with @ThreadSafe - // in class C touches field f, then all other accesses to f in C must also be thread-safe + // if a method annotated with @ThreadSafe in class C writes field f, then all other accesses to f + // in C must also be thread-safe public void writeSameFieldAsThreadSafeMethod1Bad() { + // warn here because field1 is also written in @ThreadSafe method threadSafeMethodWriteBad this.field1 = new Object(); } diff --git a/infer/tests/codetoanalyze/java/threadsafety/issues.exp b/infer/tests/codetoanalyze/java/threadsafety/issues.exp index e88a90c97..d298d0b8c 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/issues.exp +++ b/infer/tests/codetoanalyze/java/threadsafety/issues.exp @@ -1,5 +1,5 @@ -codetoanalyze/java/threadsafety/Alias.java, void Alias.bar(A,A), 5, THREAD_SAFETY_VIOLATION, [,access to `&b.A.f`,,access to `&this.Alias.a.A.f`] -codetoanalyze/java/threadsafety/Alias.java, void Alias.foo(), 6, THREAD_SAFETY_VIOLATION, [,access to `&this.Alias.b.A.f`,,access to `&this.Alias.a.A.f`] +codetoanalyze/java/threadsafety/Alias.java, void Alias.bar(A,A), 5, THREAD_SAFETY_VIOLATION, [,access to `&b.A.f`,,access to `&this.Alias.a.A.f`] +codetoanalyze/java/threadsafety/Alias.java, void Alias.foo(), 6, THREAD_SAFETY_VIOLATION, [,access to `&this.Alias.b.A.f`,,access to `&this.Alias.a.A.f`] codetoanalyze/java/threadsafety/AndroidModels.java, void AndroidModels.someResourceMethodsNotFunctionalBad(), 2, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.AndroidModels.mField`] codetoanalyze/java/threadsafety/Annotations.java, boolean Annotations.FP_functionalAcrossUnboxingOk(), 2, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Annotations.mBool2`] codetoanalyze/java/threadsafety/Annotations.java, double Annotations.functionalDoubleBad(), 2, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Annotations.mDouble`] @@ -10,22 +10,22 @@ codetoanalyze/java/threadsafety/Annotations.java, void Annotations.conditional2_ codetoanalyze/java/threadsafety/Annotations.java, void Annotations.functionalAndNonfunctionalBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Annotations.mInt`] codetoanalyze/java/threadsafety/Annotations.java, void Annotations.mutateOffUiThreadBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Annotations.f`] codetoanalyze/java/threadsafety/Annotations.java, void Annotations.mutateSubfieldOfConfinedBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Annotations.encapsulatedField.codetoanalyze.java.checkers.Obj.f`] -codetoanalyze/java/threadsafety/Annotations.java, void Annotations.read_from_non_confined_method_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Annotations.zz`,,access to `&this.codetoanalyze.java.checkers.Annotations.zz`] -codetoanalyze/java/threadsafety/Annotations.java, void Annotations.read_off_UI_thread_Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Annotations.f`,,call to void Annotations.setF(Object),access to `&this.codetoanalyze.java.checkers.Annotations.f`] +codetoanalyze/java/threadsafety/Annotations.java, void Annotations.read_from_non_confined_method_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Annotations.zz`,,access to `&this.codetoanalyze.java.checkers.Annotations.zz`] +codetoanalyze/java/threadsafety/Annotations.java, void Annotations.read_off_UI_thread_Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Annotations.f`,,call to void Annotations.setF(Object),access to `&this.codetoanalyze.java.checkers.Annotations.f`] codetoanalyze/java/threadsafety/Annotations.java, void ThreadSafeAlias.threadSafeAliasBad1(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeAlias.field`] codetoanalyze/java/threadsafety/Annotations.java, void ThreadSafeAlias.threadSafeAliasBad2(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeAlias.field`] -codetoanalyze/java/threadsafety/Arrays.java, String Arrays.readWriteRaceBad(String), 4, THREAD_SAFETY_VIOLATION, [,access to `&this.Arrays.strArr1.[_]`,,access to `&this.Arrays.strArr1.[_]`] +codetoanalyze/java/threadsafety/Arrays.java, String Arrays.readWriteRaceBad(String), 4, THREAD_SAFETY_VIOLATION, [,access to `&this.Arrays.strArr1.[_]`,,access to `&this.Arrays.strArr1.[_]`] codetoanalyze/java/threadsafety/Arrays.java, void Arrays.arrayParameterWriteBad(int[]), 1, THREAD_SAFETY_VIOLATION, [access to `&name1.[_]`] codetoanalyze/java/threadsafety/Arrays.java, void Arrays.writeWriteRaceBad(String), 1, THREAD_SAFETY_VIOLATION, [access to `&this.Arrays.strArr1.[_]`] -codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.buildThenMutateBad(Builders$Obj), 2, THREAD_SAFETY_VIOLATION, [,call to Builders$Obj$Builder Builders$Obj$Builder.setFromObj(Builders$Obj),access to `&input.codetoanalyze.java.checkers.Builders$Obj.g`,,access to `&o.codetoanalyze.java.checkers.Builders$Obj.g`] +codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.buildThenMutateBad(Builders$Obj), 2, THREAD_SAFETY_VIOLATION, [,call to Builders$Obj$Builder Builders$Obj$Builder.setFromObj(Builders$Obj),access to `&input.codetoanalyze.java.checkers.Builders$Obj.g`,,access to `&o.codetoanalyze.java.checkers.Builders$Obj.g`] codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.buildThenMutateBad(Builders$Obj), 3, THREAD_SAFETY_VIOLATION, [access to `&input.codetoanalyze.java.checkers.Builders$Obj.g`] codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.mutateBad(Builders$Obj), 1, THREAD_SAFETY_VIOLATION, [access to `&o.codetoanalyze.java.checkers.Builders$Obj.g`] codetoanalyze/java/threadsafety/Builders.java, void TopLevelBuilder.setG(String), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.TopLevelBuilder.g`] codetoanalyze/java/threadsafety/Constructors.java, Constructors Constructors.singletonBad(), 2, THREAD_SAFETY_VIOLATION, [call to Constructors.(Object),access to `&#GB$Constructors.Constructors.staticField`] codetoanalyze/java/threadsafety/Constructors.java, Constructors.(), 1, THREAD_SAFETY_VIOLATION, [access to `&#GB$Constructors.Constructors.staticField`] codetoanalyze/java/threadsafety/Constructors.java, Constructors.(Constructors), 1, THREAD_SAFETY_VIOLATION, [access to `&o.Constructors.field`] -codetoanalyze/java/threadsafety/Containers.java, boolean Containers.listReadBad(String), 1, THREAD_SAFETY_VIOLATION, [,Read of container `&this.codetoanalyze.java.checkers.Containers.mList` via call to `contains`,,Write to container `&this.codetoanalyze.java.checkers.Containers.mList` via call to `set`] -codetoanalyze/java/threadsafety/Containers.java, int Containers.readSimpleArrayMap(), 1, THREAD_SAFETY_VIOLATION, [,Read of container `&this.codetoanalyze.java.checkers.Containers.si_map` via call to `get`,,Write to container `&this.codetoanalyze.java.checkers.Containers.si_map` via call to `put`] +codetoanalyze/java/threadsafety/Containers.java, boolean Containers.listReadBad(String), 1, THREAD_SAFETY_VIOLATION, [,Read of container `&this.codetoanalyze.java.checkers.Containers.mList` via call to `contains`,,Write to container `&this.codetoanalyze.java.checkers.Containers.mList` via call to `set`] +codetoanalyze/java/threadsafety/Containers.java, int Containers.readSimpleArrayMap(), 1, THREAD_SAFETY_VIOLATION, [,Read of container `&this.codetoanalyze.java.checkers.Containers.si_map` via call to `get`,,Write to container `&this.codetoanalyze.java.checkers.Containers.si_map` via call to `put`] codetoanalyze/java/threadsafety/Containers.java, void Containers.addToSimpleArrayMapBad(SimpleArrayMap), 1, THREAD_SAFETY_VIOLATION, [Write to container `&map` via call to `put`] codetoanalyze/java/threadsafety/Containers.java, void Containers.addToSparseArrayBad(SparseArray), 1, THREAD_SAFETY_VIOLATION, [Write to container `&sparseArray` via call to `put`] codetoanalyze/java/threadsafety/Containers.java, void Containers.addToSparseArrayCompatBad(SparseArrayCompat), 1, THREAD_SAFETY_VIOLATION, [Write to container `&sparseArray` via call to `put`] @@ -55,41 +55,41 @@ codetoanalyze/java/threadsafety/Locks.java, void Locks.negatedReentrantLockTryLo codetoanalyze/java/threadsafety/Locks.java, void Locks.tryLockNoCheckBad(), 2, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Locks.f`] codetoanalyze/java/threadsafety/Locks.java, void Locks.tryLockWrongBranchBad(), 3, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.Locks.f`] codetoanalyze/java/threadsafety/Ownership.java, Ownership.(Obj,Object), 1, THREAD_SAFETY_VIOLATION, [access to `&obj.codetoanalyze.java.checkers.Obj.f`] -codetoanalyze/java/threadsafety/Ownership.java, int Ownership.readGlobalBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&#GB$codetoanalyze.java.checkers.Ownership.codetoanalyze.java.checkers.Ownership.global`,,access to `&#GB$codetoanalyze.java.checkers.Ownership.codetoanalyze.java.checkers.Ownership.global`] +codetoanalyze/java/threadsafety/Ownership.java, int Ownership.readGlobalBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&#GB$codetoanalyze.java.checkers.Ownership.codetoanalyze.java.checkers.Ownership.global`,,access to `&#GB$codetoanalyze.java.checkers.Ownership.codetoanalyze.java.checkers.Ownership.global`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.cantOwnThisBad(), 1, THREAD_SAFETY_VIOLATION, [call to void Ownership.setField(Obj),access to `&this.codetoanalyze.java.checkers.Ownership.field`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.castThenCallBad(), 2, THREAD_SAFETY_VIOLATION, [call to void Ownership.castThenCall(Obj),call to void Subclass.doWrite(),access to `&this.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.castThenReturnBad(), 2, THREAD_SAFETY_VIOLATION, [access to `n$5.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.conditionalAliasBad(Obj), 1, THREAD_SAFETY_VIOLATION, [call to void Ownership.conditionalAlias(Obj,Obj),access to `&alias.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.notOwnedInCalleeBad(Obj), 1, THREAD_SAFETY_VIOLATION, [call to void Ownership.mutateIfNotNull(Obj),access to `&o.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.notPropagatingOwnershipToAccessPathRootedAtFormalBad(Obj), 1, THREAD_SAFETY_VIOLATION, [access to `&m.codetoanalyze.java.checkers.Obj.g`] -codetoanalyze/java/threadsafety/Ownership.java, void Ownership.notPropagatingOwnershipToUnownedLocalAccessPathBad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Ownership.field`,,call to void Ownership.setField(Obj),access to `&this.codetoanalyze.java.checkers.Ownership.field`] +codetoanalyze/java/threadsafety/Ownership.java, void Ownership.notPropagatingOwnershipToUnownedLocalAccessPathBad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Ownership.field`,,call to void Ownership.setField(Obj),access to `&this.codetoanalyze.java.checkers.Ownership.field`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.notPropagatingOwnershipToUnownedLocalAccessPathBad(), 3, THREAD_SAFETY_VIOLATION, [access to `&m.codetoanalyze.java.checkers.Obj.g`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.ownInOneBranchBad(Obj,boolean), 5, THREAD_SAFETY_VIOLATION, [access to `&formal.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.reassignParamToUnownedBad(), 1, THREAD_SAFETY_VIOLATION, [call to void Ownership.reassignParamToUnowned(Obj),access to `&o.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.reassignToFormalBad(Obj), 2, THREAD_SAFETY_VIOLATION, [access to `&formal.codetoanalyze.java.checkers.Obj.g`] -codetoanalyze/java/threadsafety/Ownership.java, void Ownership.reassignToFormalBad(Obj), 3, THREAD_SAFETY_VIOLATION, [,access to `&formal.codetoanalyze.java.checkers.Obj.g`,,access to `&formal.codetoanalyze.java.checkers.Obj.g`] +codetoanalyze/java/threadsafety/Ownership.java, void Ownership.reassignToFormalBad(Obj), 3, THREAD_SAFETY_VIOLATION, [,access to `&formal.codetoanalyze.java.checkers.Obj.g`,,access to `&formal.codetoanalyze.java.checkers.Obj.g`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.writeToNotOwnedInCalleeBad1(Obj), 1, THREAD_SAFETY_VIOLATION, [call to void Ownership.writeToFormal(Obj),access to `&formal.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.writeToNotOwnedInCalleeBad2(), 2, THREAD_SAFETY_VIOLATION, [call to void Ownership.writeToFormal(Obj),access to `&formal.codetoanalyze.java.checkers.Obj.f`] codetoanalyze/java/threadsafety/Ownership.java, void Ownership.writeToNotOwnedInCalleeBad3(Obj), 1, THREAD_SAFETY_VIOLATION, [call to void Ownership.callWriteToFormal(Obj),call to void Ownership.writeToFormal(Obj),access to `&formal.codetoanalyze.java.checkers.Obj.f`] -codetoanalyze/java/threadsafety/Ownership.java, void Ownership.writeToOwnedInCalleeOk2(), 4, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Ownership.field`,,access to `&this.codetoanalyze.java.checkers.Ownership.field`] +codetoanalyze/java/threadsafety/Ownership.java, void Ownership.writeToOwnedInCalleeOk2(), 4, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.Ownership.field`,,access to `&this.codetoanalyze.java.checkers.Ownership.field`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional2_bad(boolean), 6, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.ff`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional_isMainThread_ElseBranch_Bad(), 7, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.ff`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional_isMainThread_Negation_Bad(), 3, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.ff`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.conditional_isUiThread_ElseBranch_Bad(), 7, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.ff`] codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.confusedAssertBad(boolean), 7, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.mFld`] -codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.readProtectedUnthreadedBad(), 3, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`,,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`] -codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.read_unprotected_unthreaded1_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f1`,,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f1`] -codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.read_unprotected_unthreaded_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`,,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`] -codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.callUnprotecteReadInCallee(), 1, THREAD_SAFETY_VIOLATION, [,call to Object ReadWriteRaces.unprotectedReadInCallee(),access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`] -codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.unprotectedRead1(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`] -codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.unprotectedRead2(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field2`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field2`] -codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.unprotectedRead3(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field3`,,call to void ReadWriteRaces.syncWrite3(),access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field3`] -codetoanalyze/java/threadsafety/ReadWriteRaces.java, void ReadWriteRaces.m1(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.racy`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.racy`] +codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.readProtectedUnthreadedBad(), 3, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`,,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`] +codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.read_unprotected_unthreaded1_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f1`,,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f1`] +codetoanalyze/java/threadsafety/RaceWithMainThread.java, void RaceWithMainThread.read_unprotected_unthreaded_Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`,,access to `&this.codetoanalyze.java.checkers.RaceWithMainThread.f`] +codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.callUnprotecteReadInCallee(), 1, THREAD_SAFETY_VIOLATION, [,call to Object ReadWriteRaces.unprotectedReadInCallee(),access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`] +codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.unprotectedRead1(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field1`] +codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.unprotectedRead2(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field2`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field2`] +codetoanalyze/java/threadsafety/ReadWriteRaces.java, Object ReadWriteRaces.unprotectedRead3(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field3`,,call to void ReadWriteRaces.syncWrite3(),access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.field3`] +codetoanalyze/java/threadsafety/ReadWriteRaces.java, void ReadWriteRaces.m1(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.racy`,,access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.racy`] codetoanalyze/java/threadsafety/ReadWriteRaces.java, void ReadWriteRaces.m2(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.racy`] codetoanalyze/java/threadsafety/ReadWriteRaces.java, void ReadWriteRaces.m3(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ReadWriteRaces.racy`] -codetoanalyze/java/threadsafety/ReadWriteRaces.java, void ReadWriteRaces.readInCalleeOutsideSyncBad(int), 1, THREAD_SAFETY_VIOLATION, [,call to int C.get(),access to `&this.codetoanalyze.java.checkers.C.x`,,call to void C.set(int),access to `&this.codetoanalyze.java.checkers.C.x`] -codetoanalyze/java/threadsafety/SubFld.java, int SubFld.getG(), 6, THREAD_SAFETY_VIOLATION, [,call to int SuperFld.getG(),access to `&this.SuperFld.g`,,access to `&this.SuperFld.g`] -codetoanalyze/java/threadsafety/ThreadSafeExample.java, Object ThreadSafeExample.FP_lazyInitOk(), 6, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.sStaticField`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.sStaticField`] +codetoanalyze/java/threadsafety/ReadWriteRaces.java, void ReadWriteRaces.readInCalleeOutsideSyncBad(int), 1, THREAD_SAFETY_VIOLATION, [,call to int C.get(),access to `&this.codetoanalyze.java.checkers.C.x`,,call to void C.set(int),access to `&this.codetoanalyze.java.checkers.C.x`] +codetoanalyze/java/threadsafety/SubFld.java, int SubFld.getG(), 6, THREAD_SAFETY_VIOLATION, [,call to int SuperFld.getG(),access to `&this.SuperFld.g`,,access to `&this.SuperFld.g`] +codetoanalyze/java/threadsafety/ThreadSafeExample.java, Object ThreadSafeExample.FP_lazyInitOk(), 6, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.sStaticField`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.sStaticField`] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ExtendsThreadSafeExample.newmethodBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ExtendsThreadSafeExample.field`] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ExtendsThreadSafeExample.tsOK(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ExtendsThreadSafeExample.field`] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.callPublicMethodBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.assignInPrivateMethodOk(),access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.f`] @@ -99,17 +99,17 @@ codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.o codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.recursiveBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.f`] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.tsBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeExample.f`] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void YesThreadSafeExtendsNotThreadSafeExample.subsubmethodBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.YesThreadSafeExtendsNotThreadSafeExample.subsubfield`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.readSameFieldAsThreadSafeMethod1Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.readSameFieldAsThreadSafeMethod2Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.readSameFieldAsThreadSafeMethodWhileSynchronized1Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.synchronizedReadBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field5`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field5`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.threadSafeMethodReadBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field2`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field2`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethodsSubclass.readThreadSafeFieldOfOverrideBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.readSameFieldAsThreadSafeMethod1Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.readSameFieldAsThreadSafeMethod2Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.readSameFieldAsThreadSafeMethodWhileSynchronized1Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.synchronizedReadBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field5`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field5`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethods.threadSafeMethodReadBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field2`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field2`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, Object ThreadSafeMethodsSubclass.readThreadSafeFieldOfOverrideBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`] codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.threadSafeMethodWriteBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.threadSafePrivateMethodBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field2`] codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.threadSafeVisibleForTestingMethodBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field3`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.writeSameFieldAsThreadSafeMethod1Bad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.writeSameFieldAsThreadSafeMethod2Bad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.writeSameFieldAsThreadSafeMethod1Bad(), 2, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field1`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.writeSameFieldAsThreadSafeMethod2Bad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field4`] codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethods.writeSameFieldAsThreadSafeMethod3Bad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethods.field5`] codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethodsSubclass.safeMethodOverride(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`] -codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethodsSubclass.writeThreadSafeFieldOfOverrideBad(), 1, THREAD_SAFETY_VIOLATION, [access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`] +codetoanalyze/java/threadsafety/ThreadSafeMethods.java, void ThreadSafeMethodsSubclass.writeThreadSafeFieldOfOverrideBad(), 1, THREAD_SAFETY_VIOLATION, [,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`,,access to `&this.codetoanalyze.java.checkers.ThreadSafeMethodsSubclass.subclassField`]