[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"
"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 =
CLOpt.mk_bool ~deprecated:["trace_join"] ~long:"trace-join"
"Detailed tracing information during prop join operations"
@ -1656,6 +1661,7 @@ and test = !test
and test_filtering = !test_filtering
and testing_mode = !testing_mode
and threadsafety = !threadsafety
and threadsafe_aliases = !threadsafe_aliases
and trace_error = !trace_error
and trace_ondemand = !trace_ondemand
and trace_join = !trace_join

@ -322,6 +322,7 @@ val test : bool
val test_filtering : bool
val testing_mode : bool
val threadsafety : bool
val threadsafe_aliases : Yojson.Basic.json
val trace_error : bool
val trace_ondemand : 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_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 f (annot, _) =
Annotations.annot_ends_with annot Annotations.thread_safe &&
let f ((annot : Annot.t), _) =
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
| ["false"] -> false
| _ -> 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 {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface MyThreadSafeAlias1 {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
@interface MyThreadSafeAlias2 {
}
interface Interface {
@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
class Annotations implements Interface {
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.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 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.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]

Loading…
Cancel
Save