From 618e9c93385db071b4b2bc2cb912cc2786364607 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Wed, 18 Jan 2017 20:24:29 -0800 Subject: [PATCH] [thread-safety] add @AssumeThreadSafe annotation to assume thread-safety of a method without checking it Reviewed By: peterogithub Differential Revision: D4433402 fbshipit-source-id: 742ad51 --- .../infer/annotation/AssumeThreadSafe.java | 23 +++++++++++++++++++ infer/src/checkers/ThreadSafety.ml | 6 ++++- infer/src/checkers/annotations.ml | 4 ++++ infer/src/checkers/annotations.mli | 1 + .../java/threadsafety/Annotations.java | 6 +++++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 infer/annotations/com/facebook/infer/annotation/AssumeThreadSafe.java diff --git a/infer/annotations/com/facebook/infer/annotation/AssumeThreadSafe.java b/infer/annotations/com/facebook/infer/annotation/AssumeThreadSafe.java new file mode 100644 index 000000000..7e0f51e3c --- /dev/null +++ b/infer/annotations/com/facebook/infer/annotation/AssumeThreadSafe.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2004 - 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 com.facebook.infer.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** assume that a method is thread-safe without actually checking it (as opposed to @ThreadSafe, + which does check). useful for suppressing warnings involving benign races */ + +@Target({ ElementType.METHOD }) +@Retention(RetentionPolicy.CLASS) +public @interface AssumeThreadSafe { +} diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index 30bb9c8bb..52f448398 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -315,6 +315,9 @@ let runs_on_ui_thread proc_desc = (fun annot -> Annotations.ia_is_ui_thread annot || Annotations.ia_is_on_event annot) proc_desc +let is_assumed_thread_safe pdesc = + is_annotated Annotations.ia_is_assume_thread_safe pdesc + (* return true if we should compute a summary for the procedure. if this returns false, we won't analyze the procedure or report any warnings on it *) (* note: in the future, we will want to analyze the procedures in all of these cases in order to @@ -326,7 +329,8 @@ let should_analyze_proc pdesc tenv = not (is_call_to_builder_class_method pn) && not (is_call_to_immutable_collection_method tenv pn) && not (runs_on_ui_thread pdesc) && - not (is_thread_confined_method tenv pdesc) + not (is_thread_confined_method tenv pdesc) && + not (is_assumed_thread_safe pdesc) (* return true if we should report on unprotected accesses during the procedure *) let should_report_on_proc (_, tenv, proc_name, proc_desc) = diff --git a/infer/src/checkers/annotations.ml b/infer/src/checkers/annotations.ml index 53f586727..a3e75b99c 100644 --- a/infer/src/checkers/annotations.ml +++ b/infer/src/checkers/annotations.ml @@ -123,6 +123,7 @@ let guarded_by = "GuardedBy" let thread_safe = "ThreadSafe" let thread_safe_method = "ThreadSafeMethod" let not_thread_safe = "NotThreadSafe" +let assume_thread_safe = "AssumeThreadSafe" let ui_thread = "UiThread" let any_thread = "AnyThread" let for_ui_thread = "ForUiThread" @@ -138,6 +139,9 @@ let ia_is_thread_safe ia = let ia_is_thread_safe_method ia = ia_ends_with ia thread_safe_method +let ia_is_assume_thread_safe ia = + ia_ends_with ia assume_thread_safe + let ia_is_nullable ia = ia_ends_with ia nullable diff --git a/infer/src/checkers/annotations.mli b/infer/src/checkers/annotations.mli index 692b888bd..b995579a1 100644 --- a/infer/src/checkers/annotations.mli +++ b/infer/src/checkers/annotations.mli @@ -102,6 +102,7 @@ val ia_is_guarded_by : Annot.Item.t -> bool val ia_is_not_thread_safe : Annot.Item.t -> bool val ia_is_thread_safe : Annot.Item.t -> bool val ia_is_thread_safe_method : Annot.Item.t -> bool +val ia_is_assume_thread_safe : Annot.Item.t -> bool val ia_is_ui_thread : Annot.Item.t -> bool val ia_is_thread_confined : Annot.Item.t -> bool diff --git a/infer/tests/codetoanalyze/java/threadsafety/Annotations.java b/infer/tests/codetoanalyze/java/threadsafety/Annotations.java index 28003bb08..3fbabb303 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/Annotations.java +++ b/infer/tests/codetoanalyze/java/threadsafety/Annotations.java @@ -18,6 +18,7 @@ import javax.annotation.concurrent.ThreadSafe; import android.support.annotation.UiThread; +import com.facebook.infer.annotation.AssumeThreadSafe; import com.facebook.infer.annotation.ThreadConfined; /** tests for classes and method annotations that are meaningful w.r.t thread-safety */ @@ -88,4 +89,9 @@ class Annotations { this.f = new Object(); } + @AssumeThreadSafe + public void assumeThreadSafeOk() { + this.f = new Object(); + } + }