[thread-safety] enable defining aliases of @ThreadSafe in .inferconfig

Reviewed By: peterogithub

Differential Revision: D4662764

fbshipit-source-id: c202509
master
Sam Blackshear 8 years ago committed by Facebook Github Bot
parent 1ef7c253b2
commit 5134ea36ed

@ -1297,6 +1297,11 @@ and testing_mode =
CLOpt.mk_bool ~deprecated:["testing_mode"; "-testing_mode"] ~long:"testing-mode" ~short:"tm" CLOpt.mk_bool ~deprecated:["testing_mode"; "-testing_mode"] ~long:"testing-mode" ~short:"tm"
"Mode for testing, where no headers are translated, and dot files are created (clang only)" "Mode for testing, where no headers are translated, and dot files are created (clang only)"
and threadsafe_aliases =
CLOpt.mk_json ~long:"threadsafe-aliases"
~parse_mode:CLOpt.(Infer [Checkers])
"Specify custom annotations that should be considered aliases of @ThreadSafe"
and trace_join = and trace_join =
CLOpt.mk_bool ~deprecated:["trace_join"] ~long:"trace-join" CLOpt.mk_bool ~deprecated:["trace_join"] ~long:"trace-join"
"Detailed tracing information during prop join operations" "Detailed tracing information during prop join operations"
@ -1656,6 +1661,7 @@ and test = !test
and test_filtering = !test_filtering and test_filtering = !test_filtering
and testing_mode = !testing_mode and testing_mode = !testing_mode
and threadsafety = !threadsafety and threadsafety = !threadsafety
and threadsafe_aliases = !threadsafe_aliases
and trace_error = !trace_error and trace_error = !trace_error
and trace_ondemand = !trace_ondemand and trace_ondemand = !trace_ondemand
and trace_join = !trace_join and trace_join = !trace_join

@ -322,6 +322,7 @@ val test : bool
val test_filtering : bool val test_filtering : bool
val testing_mode : bool val testing_mode : bool
val threadsafety : bool val threadsafety : bool
val threadsafe_aliases : Yojson.Basic.json
val trace_error : bool val trace_error : bool
val trace_ondemand : bool val trace_ondemand : bool
val trace_join : bool val trace_join : bool

@ -679,11 +679,19 @@ let runs_on_ui_thread proc_desc =
Annotations.ia_is_on_unbind annot || Annotations.ia_is_on_unbind annot ||
Annotations.ia_is_on_unmount annot) Annotations.ia_is_on_unmount annot)
let threadsafe_annotations =
Annotations.thread_safe ::
(ThreadSafetyConfig.AnnotationAliases.of_json Config.threadsafe_aliases)
(* returns true if the annotation is @ThreadSafe or @ThreadSafe(enableChecks = true) *) (* returns true if the annotation is @ThreadSafe, @ThreadSafe(enableChecks = true), or is defined
as an alias of @ThreadSafe in a .inferconfig file. *)
let is_thread_safe item_annot = let is_thread_safe item_annot =
let f (annot, _) = let f ((annot : Annot.t), _) =
Annotations.annot_ends_with annot Annotations.thread_safe && List.exists
~f:(fun annot_string ->
Annotations.annot_ends_with annot annot_string ||
String.equal annot.class_name annot_string)
threadsafe_annotations &&
match annot.Annot.parameters with match annot.Annot.parameters with
| ["false"] -> false | ["false"] -> false
| _ -> true in | _ -> true in

@ -0,0 +1,19 @@
(*
* Copyright (c) 2017 - 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.
*)
open! IStd
module F = Format
module AnnotationAliases = struct
let of_json = function
| `List aliases -> List.map ~f:Yojson.Basic.Util.to_string aliases
| _ -> failwith "Couldn't parse thread-safety annotation aliases; expected list of strings"
end

@ -0,0 +1,18 @@
(*
* Copyright (c) 2017 - 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.
*)
open! IStd
module F = Format
(** List of annotations that should be considered aliases of @ThreadSafe *)
module AnnotationAliases : sig
val of_json : Yojson.Basic.json -> string list
end

@ -0,0 +1,3 @@
{
"threadsafe-aliases": ["MyThreadSafeAlias1", "codetoanalyze.java.checkers.MyThreadSafeAlias2"]
}

@ -48,6 +48,16 @@ import com.facebook.infer.annotation.ReturnsOwnership;
@interface OnUnmount { @interface OnUnmount {
} }
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface MyThreadSafeAlias1 {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface MyThreadSafeAlias2 {
}
interface Interface { interface Interface {
@Functional Object functionalMethod(); @Functional Object functionalMethod();
@ -64,6 +74,21 @@ class AssumedThreadSafe {
} }
} }
// this annotation is defined as an alias for @ThreadSafe in .inferconfig
class ThreadSafeAlias {
Object field;
@MyThreadSafeAlias1
void threadSafeAliasBad1() {
this.field = new Object();
}
@MyThreadSafeAlias2
void threadSafeAliasBad2() {
this.field = new Object();
}
}
@ThreadSafe @ThreadSafe
class Annotations implements Interface { class Annotations implements Interface {
Object f; Object f;

@ -7,6 +7,8 @@ codetoanalyze/java/threadsafety/Annotations.java, long Annotations.functionaLong
codetoanalyze/java/threadsafety/Annotations.java, void Annotations.functionalAndNonfunctionalBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Annotations.mInt] codetoanalyze/java/threadsafety/Annotations.java, void Annotations.functionalAndNonfunctionalBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Annotations.mInt]
codetoanalyze/java/threadsafety/Annotations.java, void Annotations.mutateOffUiThreadBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Annotations.f] codetoanalyze/java/threadsafety/Annotations.java, void Annotations.mutateOffUiThreadBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Annotations.f]
codetoanalyze/java/threadsafety/Annotations.java, void Annotations.mutateSubfieldOfConfinedBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Annotations.encapsulatedField.codetoanalyze.java.checkers.Obj.f] codetoanalyze/java/threadsafety/Annotations.java, void Annotations.mutateSubfieldOfConfinedBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Annotations.encapsulatedField.codetoanalyze.java.checkers.Obj.f]
codetoanalyze/java/threadsafety/Annotations.java, void ThreadSafeAlias.threadSafeAliasBad1(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.ThreadSafeAlias.field]
codetoanalyze/java/threadsafety/Annotations.java, void ThreadSafeAlias.threadSafeAliasBad2(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.ThreadSafeAlias.field]
codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.buildThenMutateBad(Builders$Obj), 3, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Builders$Obj.g] codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.buildThenMutateBad(Builders$Obj), 3, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Builders$Obj.g]
codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.mutateBad(Builders$Obj), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Builders$Obj.g] codetoanalyze/java/threadsafety/Builders.java, Builders$Obj Builders.mutateBad(Builders$Obj), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.Builders$Obj.g]
codetoanalyze/java/threadsafety/Constructors.java, Constructors Constructors.singletonBad(), 2, THREAD_SAFETY_VIOLATION, [call to Constructors.<init>(Object),access to Constructors.staticField] codetoanalyze/java/threadsafety/Constructors.java, Constructors Constructors.singletonBad(), 2, THREAD_SAFETY_VIOLATION, [call to Constructors.<init>(Object),access to Constructors.staticField]

Loading…
Cancel
Save