[biabd] stop depending on nullsafe

Summary:
Based on a shrewd observation by mityal, we can copy a little bit of
code from nullsafe and cut the dependency between biabduction and
nullsafe. The trick was to notice that biabduction doesn't use the full
power of the functions it was calling.

Reviewed By: mityal

Differential Revision: D21282656

fbshipit-source-id: 906847c26
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent f519d3e183
commit 43586dd8c5

@ -66,6 +66,26 @@ type t =
; ret_type: Typ.t (** return type *) ; ret_type: Typ.t (** return type *)
; has_added_return_param: bool (** whether or not a return param was added *) } ; has_added_return_param: bool (** whether or not a return param was added *) }
let get_annotated_formals {method_annotation= {params}; formals} =
let rec zip_params ial parl =
match (ial, parl) with
| ia :: ial', param :: parl' ->
(param, ia) :: zip_params ial' parl'
| [], param :: parl' ->
(* List of annotations exhausted before the list of params -
treat lack of annotation info as an empty annotation *)
(param, Annot.Item.empty) :: zip_params [] parl'
| [], [] ->
[]
| _ :: _, [] ->
(* List of params exhausted before the list of annotations -
this should never happen *)
assert false
in
(* zip formal params with annotation *)
List.rev (zip_params (List.rev params) (List.rev formals))
let default translation_unit proc_name = let default translation_unit proc_name =
{ access= PredSymb.Default { access= PredSymb.Default
; captured= [] ; captured= []
@ -150,7 +170,11 @@ let pp f
pp_bool_default ~default:default.is_defined "is_defined" is_defined f () ; pp_bool_default ~default:default.is_defined "is_defined" is_defined f () ;
pp_bool_default ~default:default.is_java_synchronized_method "is_java_synchronized_method" pp_bool_default ~default:default.is_java_synchronized_method "is_java_synchronized_method"
is_java_synchronized_method f () ; is_java_synchronized_method f () ;
if not ([%compare.equal : Procname.t option] default.passed_as_noescape_block_to passed_as_noescape_block_to) then if
not
([%compare.equal: Procname.t option] default.passed_as_noescape_block_to
passed_as_noescape_block_to)
then
F.fprintf f "; passed_as_noescape_block_to %a" (Pp.option Procname.pp) F.fprintf f "; passed_as_noescape_block_to %a" (Pp.option Procname.pp)
passed_as_noescape_block_to ; passed_as_noescape_block_to ;
pp_bool_default ~default:default.is_no_return "is_no_return" is_no_return f () ; pp_bool_default ~default:default.is_no_return "is_no_return" is_no_return f () ;

@ -55,4 +55,6 @@ val default : SourceFile.t -> Procname.t -> t
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
val get_annotated_formals : t -> ((Mangled.t * Typ.t) * Annot.Item.t) list
module SQLite : SqliteUtils.Data with type t = t module SQLite : SqliteUtils.Data with type t = t

@ -1144,11 +1144,17 @@ let rec iter_rearrange analysis_data pname tenv lexp typ_from_instr prop iter in
res res
let param_has_annot predicate pvar params_with_annotations =
List.exists
~f:(function
| (mangled, _), param_annotation_deprecated ->
Mangled.equal mangled (Pvar.get_name pvar) && predicate param_annotation_deprecated )
params_with_annotations
let var_has_annotation pdesc is_annotation pvar = let var_has_annotation pdesc is_annotation pvar =
let ann_sig = Procdesc.get_attributes pdesc |> ProcAttributes.get_annotated_formals
Models.get_modelled_annotated_signature_for_biabduction (Procdesc.get_attributes pdesc) |> param_has_annot is_annotation pvar
in
AnnotatedSignature.param_has_annot is_annotation pvar ann_sig
let attr_has_annot is_annotation tenv prop exp = let attr_has_annot is_annotation tenv prop exp =

@ -75,37 +75,15 @@ let extract_nullability ~is_callee_in_trust_list ~nullsafe_mode ~is_third_party
(return_nullability, params_nullability) (return_nullability, params_nullability)
let get ~is_callee_in_trust_list ~nullsafe_mode proc_attributes : t = let get ~is_callee_in_trust_list ~nullsafe_mode
let Annot.Method.{return= ret_annotation; params= original_params_annotation} = ( {ProcAttributes.proc_name; ret_type; method_annotation= {return= ret_annotation}} as
proc_attributes.ProcAttributes.method_annotation proc_attributes ) : t =
in
let formals = proc_attributes.ProcAttributes.formals in
let ret_type = proc_attributes.ProcAttributes.ret_type in
let procname = proc_attributes.ProcAttributes.proc_name in
let is_third_party = let is_third_party =
ThirdPartyAnnotationInfo.is_third_party_proc ThirdPartyAnnotationInfo.is_third_party_proc
(ThirdPartyAnnotationGlobalRepo.get_repo ()) (ThirdPartyAnnotationGlobalRepo.get_repo ())
procname proc_name
in
(* zip formal params with annotation *)
let params_with_annotations =
let rec zip_params ial parl =
match (ial, parl) with
| ia :: ial', param :: parl' ->
(param, ia) :: zip_params ial' parl'
| [], param :: parl' ->
(* List of annotations exhausted before the list of params -
treat lack of annotation info as an empty annotation *)
(param, Annot.Item.empty) :: zip_params [] parl'
| [], [] ->
[]
| _ :: _, [] ->
(* List of params exhausted before the list of annotations -
this should never happen *)
assert false
in
List.rev (zip_params (List.rev original_params_annotation) (List.rev formals))
in in
let params_with_annotations = ProcAttributes.get_annotated_formals proc_attributes in
let param_annotated_types = let param_annotated_types =
List.map params_with_annotations ~f:(fun ((_, typ), annotations) -> (typ, annotations)) List.map params_with_annotations ~f:(fun ((_, typ), annotations) -> (typ, annotations))
in in
@ -143,13 +121,6 @@ let get_for_class_under_analysis tenv proc_attributes =
{result with nullsafe_mode} {result with nullsafe_mode}
let param_has_annot predicate pvar ann_sig =
List.exists
~f:(fun {mangled; param_annotation_deprecated} ->
Mangled.equal mangled (Pvar.get_name pvar) && predicate param_annotation_deprecated )
ann_sig.params
let pp proc_name fmt annotated_signature = let pp proc_name fmt annotated_signature =
let pp_ia fmt ia = if not (List.is_empty ia) then F.fprintf fmt "%a " Annot.Item.pp ia in let pp_ia fmt ia = if not (List.is_empty ia) then F.fprintf fmt "%a " Annot.Item.pp ia in
let pp_annotated_param fmt {mangled; param_annotation_deprecated; param_annotated_type} = let pp_annotated_param fmt {mangled; param_annotation_deprecated; param_annotated_type} =
@ -171,8 +142,8 @@ let mk_ia_nullable ia =
let mark_ia_nullability ia x = if x then mk_ia_nullable ia else ia let mark_ia_nullability ia x = if x then mk_ia_nullable ia else ia
(* Override existing information about nullability for a given type and (** Override existing information about nullability for a given type and set it to either nullable
set it to either nullable or nonnull *) or nonnull *)
let set_modelled_nullability_for_annotated_type annotated_type should_set_nullable = let set_modelled_nullability_for_annotated_type annotated_type should_set_nullable =
let nullability = let nullability =
if should_set_nullable then AnnotatedNullability.Nullable ModelledNullable if should_set_nullable then AnnotatedNullability.Nullable ModelledNullable

@ -28,9 +28,6 @@ and param_signature =
and model_source = InternalModel | ThirdPartyRepo of {filename: string; line_number: int} and model_source = InternalModel | ThirdPartyRepo of {filename: string; line_number: int}
[@@deriving compare] [@@deriving compare]
val param_has_annot : (Annot.Item.t -> bool) -> Pvar.t -> t -> bool
(** Check if the given parameter has an annotation in the given signature *)
val set_modelled_nullability : Procname.t -> t -> model_source -> bool * bool list -> t val set_modelled_nullability : Procname.t -> t -> model_source -> bool * bool list -> t
(** Override nullability for a function signature given its modelled nullability (for ret value and (** Override nullability for a function signature given its modelled nullability (for ret value and
params) *) params) *)

@ -27,27 +27,6 @@ let table_has_procedure table proc_name =
with Caml.Not_found -> false with Caml.Not_found -> false
(* This is used outside of nullsafe for biabduction.
If biabduction and nullsafe want to depend on common functionality, this functionality
should be refactored out in a dedicated library.
*)
let get_modelled_annotated_signature_for_biabduction proc_attributes =
let proc_name = proc_attributes.ProcAttributes.proc_name in
let annotated_signature =
AnnotatedSignature.get ~is_callee_in_trust_list:false ~nullsafe_mode:NullsafeMode.Default
proc_attributes
in
let proc_id = Procname.to_unique_id proc_name in
let lookup_models_nullable ann_sig =
try
let modelled_nullability = Hashtbl.find annotated_table_nullability proc_id in
AnnotatedSignature.set_modelled_nullability proc_name ann_sig InternalModel
modelled_nullability
with Caml.Not_found -> ann_sig
in
annotated_signature |> lookup_models_nullable
let get_unique_repr proc_name = let get_unique_repr proc_name =
let java_proc_name = let java_proc_name =
match proc_name with Procname.Java java_proc_name -> Some java_proc_name | _ -> None match proc_name with Procname.Java java_proc_name -> Some java_proc_name | _ -> None

Loading…
Cancel
Save