[biabduction] Rewrite the function resolve_java_pname in SymExec for all procnames

Reviewed By: jeremydubreil

Differential Revision: D8334702

fbshipit-source-id: 757442a
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent 113ddbb3ac
commit 776e728b63

@ -593,6 +593,8 @@ module Procname = struct
type_to_string_verbosity head verbosity ^ "," ^ param_list_to_string rest verbosity type_to_string_verbosity head verbosity ^ "," ^ param_list_to_string rest verbosity
let java_type_of_name class_name = Name.Java.Split.of_string (Name.name class_name)
(** It is the same as java_type_to_string_verbosity, but Java return types are optional because (** It is the same as java_type_to_string_verbosity, but Java return types are optional because
of constructors without type *) of constructors without type *)
let return_type_to_string j verbosity = let return_type_to_string j verbosity =
@ -734,9 +736,13 @@ module Procname = struct
end end
module Parameter = struct module Parameter = struct
(** [Some name] means the parameter is of type pointer to struct, with [name] (** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to struct, with [name]
being the name of the struct, [None] means the parameter is of some other type. *) being the name of the struct, [None] means the parameter is of some other type. *)
type t = Name.t option [@@deriving compare] type clang_parameter = Name.t option [@@deriving compare]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare]
let of_typ typ = let of_typ typ =
match typ.T.desc with T.Tptr ({desc= Tstruct name}, Pk_pointer) -> Some name | _ -> None match typ.T.desc with T.Tptr ({desc= Tstruct name}, Pk_pointer) -> Some name | _ -> None
@ -748,6 +754,9 @@ being the name of the struct, [None] means the parameter is of some other type.
in in
let string_pars = List.map ~f:name_opt_to_string parameters in let string_pars = List.map ~f:name_opt_to_string parameters in
if List.is_empty parameters then "" else "(" ^ String.concat ~sep:"," string_pars ^ ")" if List.is_empty parameters then "" else "(" ^ String.concat ~sep:"," string_pars ^ ")"
let clang_param_of_name class_name : clang_parameter = Some class_name
end end
module ObjC_Cpp = struct module ObjC_Cpp = struct
@ -764,7 +773,7 @@ being the name of the struct, [None] means the parameter is of some other type.
{ class_name: Name.t { class_name: Name.t
; kind: kind ; kind: kind
; method_name: string ; method_name: string
; parameters: Parameter.t list ; parameters: Parameter.clang_parameter list
; template_args: template_spec_info } ; template_args: template_spec_info }
[@@deriving compare] [@@deriving compare]
@ -839,6 +848,11 @@ being the name of the struct, [None] means the parameter is of some other type.
let m_str = kind_to_verbose_string osig.kind in let m_str = kind_to_verbose_string osig.kind in
Name.name osig.class_name ^ "_" ^ osig.method_name Name.name osig.class_name ^ "_" ^ osig.method_name
^ Parameter.parameters_to_string osig.parameters ^ m_str ^ Parameter.parameters_to_string osig.parameters ^ m_str
let get_parameters osig = osig.parameters
let replace_parameters new_parameters osig = {osig with parameters= new_parameters}
end end
module C = struct module C = struct
@ -846,7 +860,7 @@ being the name of the struct, [None] means the parameter is of some other type.
type t = type t =
{ name: QualifiedCppName.t { name: QualifiedCppName.t
; mangled: string option ; mangled: string option
; parameters: Parameter.t list ; parameters: Parameter.clang_parameter list
; template_args: template_spec_info } ; template_args: template_spec_info }
[@@deriving compare] [@@deriving compare]
@ -875,13 +889,18 @@ being the name of the struct, [None] means the parameter is of some other type.
plain ^ Parameter.parameters_to_string parameters plain ^ Parameter.parameters_to_string parameters
| Some s -> | Some s ->
plain ^ Parameter.parameters_to_string parameters ^ "{" ^ s ^ "}" plain ^ Parameter.parameters_to_string parameters ^ "{" ^ s ^ "}"
let get_parameters c = c.parameters
let replace_parameters new_parameters c = {c with parameters= new_parameters}
end end
module Block = struct module Block = struct
(** Type of Objective C block names. *) (** Type of Objective C block names. *)
type block_name = string [@@deriving compare] type block_name = string [@@deriving compare]
type t = {name: block_name; parameters: Parameter.t list} [@@deriving compare] type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare]
let make name parameters = {name; parameters} let make name parameters = {name; parameters}
@ -893,6 +912,11 @@ being the name of the struct, [None] means the parameter is of some other type.
bsig.name bsig.name
| Verbose -> | Verbose ->
bsig.name ^ Parameter.parameters_to_string bsig.parameters bsig.name ^ Parameter.parameters_to_string bsig.parameters
let get_parameters block = block.parameters
let replace_parameters new_parameters block = {block with parameters= new_parameters}
end end
(** Type of procedure names. *) (** Type of procedure names. *)
@ -1107,6 +1131,71 @@ being the name of the struct, [None] means the parameter is of some other type.
to_simplified_string ~withclass:true p to_simplified_string ~withclass:true p
let rec get_parameters procname =
let clang_param_to_param clang_params =
List.map ~f:(fun par -> Parameter.ClangParameter par) clang_params
in
match procname with
| Java j ->
List.map ~f:(fun par -> Parameter.JavaParameter par) (Java.get_parameters j)
| C osig ->
clang_param_to_param (C.get_parameters osig)
| ObjC_Cpp osig ->
clang_param_to_param (ObjC_Cpp.get_parameters osig)
| Block bsig ->
clang_param_to_param (Block.get_parameters bsig)
| WithBlockParameters (base, _) ->
get_parameters base
| Linters_dummy_method ->
[]
let rec replace_parameters new_parameters procname =
let params_to_java_params params =
List.map
~f:(fun param ->
match param with
| Parameter.JavaParameter par ->
par
| _ ->
Logging.(die InternalError)
"Expected Java parameters in Java procname, but got Clang parameters" params )
params
in
let params_to_clang_params params =
List.map
~f:(fun param ->
match param with
| Parameter.ClangParameter par ->
par
| _ ->
Logging.(die InternalError)
"Expected Clang parameters in Clang procname, but got Java parameters" params )
params
in
match procname with
| Java j ->
Java (Java.replace_parameters (params_to_java_params new_parameters) j)
| C osig ->
C (C.replace_parameters (params_to_clang_params new_parameters) osig)
| ObjC_Cpp osig ->
ObjC_Cpp (ObjC_Cpp.replace_parameters (params_to_clang_params new_parameters) osig)
| Block bsig ->
Block (Block.replace_parameters (params_to_clang_params new_parameters) bsig)
| WithBlockParameters (base, blocks) ->
WithBlockParameters (replace_parameters new_parameters base, blocks)
| Linters_dummy_method ->
procname
let parameter_of_name procname class_name =
match procname with
| Java _ ->
Parameter.JavaParameter (Java.java_type_of_name class_name)
| _ ->
Parameter.ClangParameter (Parameter.clang_param_of_name class_name)
(** Pretty print a proc name *) (** Pretty print a proc name *)
let pp f pn = F.pp_print_string f (to_string pn) let pp f pn = F.pp_print_string f (to_string pn)

@ -162,10 +162,6 @@ module Name : sig
val make : ?package:string -> string -> t val make : ?package:string -> string -> t
val of_string : string -> t
(** Given a package.class_name string, look for the latest dot and split the string
in two (package, class_name). *)
val java_lang_object : t val java_lang_object : t
val java_lang_string : t val java_lang_string : t
@ -365,11 +361,15 @@ module Procname : sig
end end
module Parameter : sig module Parameter : sig
(** [Some name] means the parameter is of type pointer to struct, with [name] (** Type for parameters in clang procnames, [Some name] means the parameter is of type pointer to struct, with [name]
being the name of the struct, [None] means the parameter is of some other type. *) being the name of the struct, [None] means the parameter is of some other type. *)
type t = Name.t option type clang_parameter = Name.t option [@@deriving compare]
(** Type for parameters in procnames, for java and clang. *)
type t = JavaParameter of Java.java_type | ClangParameter of clang_parameter
[@@deriving compare]
val of_typ : typ -> t val of_typ : typ -> clang_parameter
end end
module ObjC_Cpp : sig module ObjC_Cpp : sig
@ -387,11 +387,12 @@ module Procname : sig
{ class_name: Name.t { class_name: Name.t
; kind: kind ; kind: kind
; method_name: string ; method_name: string
; parameters: Parameter.t list ; parameters: Parameter.clang_parameter list
; template_args: template_spec_info } ; template_args: template_spec_info }
[@@deriving compare] [@@deriving compare]
val make : Name.t -> string -> kind -> template_spec_info -> Parameter.t list -> t val make :
Name.t -> string -> kind -> template_spec_info -> Parameter.clang_parameter list -> t
(** Create an objc procedure name from a class_name and method_name. *) (** Create an objc procedure name from a class_name and method_name. *)
val get_class_name : t -> string val get_class_name : t -> string
@ -430,10 +431,11 @@ module Procname : sig
type t = private type t = private
{ name: QualifiedCppName.t { name: QualifiedCppName.t
; mangled: string option ; mangled: string option
; parameters: Parameter.t list ; parameters: Parameter.clang_parameter list
; template_args: template_spec_info } ; template_args: template_spec_info }
val c : QualifiedCppName.t -> string -> Parameter.t list -> template_spec_info -> t val c :
QualifiedCppName.t -> string -> Parameter.clang_parameter list -> template_spec_info -> t
(** Create a C procedure name from plain and mangled name. *) (** Create a C procedure name from plain and mangled name. *)
end end
@ -441,9 +443,9 @@ module Procname : sig
(** Type of Objective C block names. *) (** Type of Objective C block names. *)
type block_name = string type block_name = string
type t = {name: block_name; parameters: Parameter.t list} [@@deriving compare] type t = {name: block_name; parameters: Parameter.clang_parameter list} [@@deriving compare]
val make : block_name -> Parameter.t list -> t val make : block_name -> Parameter.clang_parameter list -> t
end end
(** Type of procedure names. (** Type of procedure names.
@ -465,6 +467,12 @@ module Procname : sig
val equal : t -> t -> bool val equal : t -> t -> bool
val get_parameters : t -> Parameter.t list
val replace_parameters : Parameter.t list -> t -> t
val parameter_of_name : t -> Name.t -> Parameter.t
(** Hash tables with proc names as keys. *) (** Hash tables with proc names as keys. *)
module Hash : Caml.Hashtbl.S with type key = t module Hash : Caml.Hashtbl.S with type key = t

@ -624,53 +624,48 @@ let resolve_virtual_pname tenv prop actuals callee_pname call_flags : Typ.Procna
(** Resolve the name of the procedure to call based on the type of the arguments *) (** Resolve the name of the procedure to call based on the type of the arguments *)
let resolve_java_pname tenv prop args pname_java call_flags : Typ.Procname.Java.t = let resolve_pname tenv prop args pname call_flags : Typ.Procname.t =
let resolve_from_args resolved_pname_java args = let resolve_from_args resolved_pname args =
let resolved_params = let resolved_params =
List.fold2_exn List.fold2_exn
~f:(fun accu (arg_exp, _) name -> ~f:(fun accu (arg_exp, _) name ->
match resolve_typename prop arg_exp with match resolve_typename prop arg_exp with
| Some class_name -> | Some class_name ->
Typ.Name.Java.Split.of_string (Typ.Name.name class_name) :: accu Typ.Procname.parameter_of_name resolved_pname class_name :: accu
| None -> | None ->
name :: accu ) name :: accu )
~init:[] args ~init:[] args
(Typ.Procname.Java.get_parameters resolved_pname_java) (Typ.Procname.get_parameters resolved_pname)
|> List.rev |> List.rev
in in
Typ.Procname.Java.replace_parameters resolved_params resolved_pname_java Typ.Procname.replace_parameters resolved_params resolved_pname
in in
let resolved_pname_java, other_args = let resolved_pname, other_args =
let pname = Typ.Procname.Java pname_java let parameters = Typ.Procname.get_parameters pname in
and parameters = Typ.Procname.Java.get_parameters pname_java in
let match_parameters args = Int.equal (List.length args) (List.length parameters) in let match_parameters args = Int.equal (List.length args) (List.length parameters) in
match args with match args with
| [] -> | [] ->
(pname_java, []) (pname, [])
| (first_arg, _) :: other_args when call_flags.CallFlags.cf_virtual -> | (first_arg, _) :: other_args when call_flags.CallFlags.cf_virtual ->
let resolved = let resolved =
match resolve_typename prop first_arg with match resolve_typename prop first_arg with
| Some class_name -> ( | Some class_name ->
match resolve_method tenv class_name pname with resolve_method tenv class_name pname
| Typ.Procname.Java resolved_pname_java ->
resolved_pname_java
| _ ->
pname_java )
| None -> | None ->
pname_java pname
in in
(resolved, other_args) (resolved, other_args)
| _ :: other_args | _ :: other_args
when match_parameters other_args (* Non-virtual call, e.g. constructors or private methods *) -> when match_parameters other_args (* Non-virtual call, e.g. constructors or private methods *) ->
(pname_java, other_args) (pname, other_args)
| args when match_parameters args (* Static call *) -> | args when match_parameters args (* Static call *) ->
(pname_java, args) (pname, args)
| args -> | args ->
L.(die InternalError) L.(die InternalError)
"Call mismatch: method %a has %i paramters but is called with %i arguments@." "Call mismatch: method %a has %i paramters but is called with %i arguments@."
Typ.Procname.pp pname (List.length parameters) (List.length args) Typ.Procname.pp pname (List.length parameters) (List.length args)
in in
resolve_from_args resolved_pname_java other_args resolve_from_args resolved_pname other_args
(** Resolve the procedure name and run the analysis of the resolved procedure (** Resolve the procedure name and run the analysis of the resolved procedure
@ -697,13 +692,7 @@ let resolve_and_analyze tenv ~caller_pdesc prop args callee_proc_name call_flags
in in
Option.bind resolved_proc_desc_option ~f:analyze Option.bind resolved_proc_desc_option ~f:analyze
in in
let resolved_pname = let resolved_pname = resolve_pname tenv prop args callee_proc_name call_flags in
match callee_proc_name with
| Typ.Procname.Java callee_proc_name_java ->
Typ.Procname.Java (resolve_java_pname tenv prop args callee_proc_name_java call_flags)
| _ ->
callee_proc_name
in
(resolved_pname, analyze_ondemand resolved_pname) (resolved_pname, analyze_ondemand resolved_pname)

Loading…
Cancel
Save