[cleanup] restrict Java-specific utility functions to Typ.Procname.Java.t's

Reviewed By: jeremydubreil

Differential Revision: D6740465

fbshipit-source-id: 4ad717b
master
Sam Blackshear 7 years ago committed by Facebook Github Bot
parent 55ecd9b0a4
commit f7c415f7ae

@ -171,10 +171,10 @@ let inline_synthetic_method ret_id etl pdesc loc_call : Sil.instr option =
(** Find synthetic (access or bridge) Java methods in the procedure and inline them in the cfg. *)
let proc_inline_synthetic_methods cfg pdesc : unit =
let instr_inline_synthetic_method = function
| Sil.Call (ret_id, Exp.Const Const.Cfun pn, etl, loc, _) -> (
| Sil.Call (ret_id, Exp.Const Const.Cfun (Typ.Procname.Java java_pn as pn), etl, loc, _) -> (
match Typ.Procname.Hash.find cfg pn with
| pd ->
let is_access = Typ.Procname.java_is_access_method pn in
let is_access = Typ.Procname.Java.is_access_method java_pn in
let attributes = Procdesc.get_attributes pd in
let is_synthetic = attributes.is_synthetic_method in
let is_bridge = attributes.is_bridge_method in

@ -506,45 +506,9 @@ let has_block_prefix s =
false
(** Java types by name *)
let rec java_from_string : string -> t = function
| "" | "void" ->
mk Tvoid
| "int" ->
mk (Tint IInt)
| "byte" ->
mk (Tint IShort)
| "short" ->
mk (Tint IShort)
| "boolean" ->
mk (Tint IBool)
| "char" ->
mk (Tint IChar)
| "long" ->
mk (Tint ILong)
| "float" ->
mk (Tfloat FFloat)
| "double" ->
mk (Tfloat FDouble)
| typ_str when String.contains typ_str '[' ->
let stripped_typ = String.sub typ_str ~pos:0 ~len:(String.length typ_str - 2) in
mk (Tptr (mk (Tarray (java_from_string stripped_typ, None, None)), Pk_pointer))
| typ_str ->
mk (Tstruct (Name.Java.from_string typ_str))
type typ = t
module Procname = struct
type method_kind =
| Non_Static
(* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static
(* in Java, procedures called with invokestatic *)
[@@deriving compare]
let equal_method_kind = [%compare.equal : method_kind]
(** Level of verbosity of some to_string functions. *)
type detail_level = Verbose | Non_verbose | Simple [@@deriving compare]
@ -553,6 +517,13 @@ module Procname = struct
let is_verbose v = match v with Verbose -> true | _ -> false
module Java = struct
type kind =
| Non_Static
(* in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static
(* in Java, procedures called with invokestatic *)
[@@deriving compare]
(* TODO: use Mangled.t here *)
type java_type = string option * string
@ -565,7 +536,7 @@ module Procname = struct
; parameters: java_type list
; class_name: Name.t
; return_type: java_type option (* option because constructors have no return type *)
; kind: method_kind }
; kind: kind }
[@@deriving compare]
let make class_name return_type method_name parameters kind =
@ -655,6 +626,72 @@ module Procname = struct
else cls_prefix ^ j.method_name
in
method_name ^ "(" ^ params ^ ")"
let get_return_typ pname_java =
let rec java_from_string = function
| "" | "void" ->
mk Tvoid
| "int" ->
mk (Tint IInt)
| "byte" ->
mk (Tint IShort)
| "short" ->
mk (Tint IShort)
| "boolean" ->
mk (Tint IBool)
| "char" ->
mk (Tint IChar)
| "long" ->
mk (Tint ILong)
| "float" ->
mk (Tfloat FFloat)
| "double" ->
mk (Tfloat FDouble)
| typ_str when String.contains typ_str '[' ->
let stripped_typ = String.sub typ_str ~pos:0 ~len:(String.length typ_str - 2) in
mk (Tptr (mk (Tarray (java_from_string stripped_typ, None, None)), Pk_pointer))
| typ_str ->
mk (Tstruct (Name.Java.from_string typ_str))
in
let typ = java_from_string (get_return_type pname_java) in
match typ.desc with Tstruct _ -> mk (Tptr (typ, Pk_pointer)) | _ -> typ
let is_close {method_name} = String.equal method_name "close"
let is_class_initializer {method_name} = String.equal method_name "<clinit>"
let is_anonymous_inner_class_constructor {class_name} =
Name.Java.is_anonymous_inner_class_name class_name
let is_static {kind} = match kind with Static -> true | _ -> false
let is_lambda {method_name} = String.is_prefix ~prefix:"lambda$" method_name
let is_generated {method_name} = String.is_prefix ~prefix:"$" method_name
let is_access_method {method_name} =
match String.rsplit2 method_name ~on:'$' with
| Some ("access", s) ->
let is_int =
try
ignore (int_of_string s) ;
true
with Failure _ -> false
in
is_int
| _ ->
false
let is_autogen_method {method_name} = String.contains method_name '$'
(** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. *)
let is_vararg {parameters} =
match List.last parameters with Some (_, "java.lang.Object[]") -> true | _ -> false
end
(** Type of c procedure names. *)
@ -758,67 +795,6 @@ module Procname = struct
t
(** Check if the procedure name is an anonymous inner class constructor. *)
let java_is_anonymous_inner_class_constructor = function
| Java js ->
Name.Java.is_anonymous_inner_class_name js.class_name
| _ ->
false
(** Return true if the java procedure is static *)
let java_is_static = function Java j -> equal_method_kind j.kind Static | _ -> false
let java_is_lambda = function
| Java j ->
String.is_prefix ~prefix:"lambda$" j.method_name
| _ ->
false
let java_is_generated = function
| Java j ->
String.is_prefix ~prefix:"$" j.method_name
| _ ->
false
(** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. *)
let java_is_access_method = function
| Java js -> (
match String.rsplit2 js.method_name ~on:'$' with
| Some ("access", s) ->
let is_int =
try
ignore (int_of_string s) ;
true
with Failure _ -> false
in
is_int
| _ ->
false )
| _ ->
false
(** Check if the procedure name is of an auto-generated method containing '$'. *)
let java_is_autogen_method = function
| Java js ->
String.contains js.method_name '$'
| _ ->
false
(** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. *)
let java_is_vararg = function
| Java js -> (
match List.rev js.parameters with (_, "java.lang.Object[]") :: _ -> true | _ -> false )
| _ ->
false
let rec objc_cpp_replace_method_name t (new_method_name: string) =
match t with
| ObjC_Cpp osig ->
@ -909,16 +885,6 @@ module Procname = struct
false
let java_is_close = function Java js -> String.equal js.method_name "close" | _ -> false
(** [is_class_initializer pname] returns true if [pname] is a class initializer *)
let is_class_initializer = function
| Java js ->
String.equal js.method_name "<clinit>"
| _ ->
false
(** [is_infer_undefined pn] returns true if [pn] is a special Infer undefined proc *)
let is_infer_undefined pn =
match pn with
@ -1146,12 +1112,6 @@ module Procname = struct
end
end
(** Return the return type of [pname_java]. *)
let java_proc_return_typ pname_java : t =
let typ = java_from_string (Procname.Java.get_return_type pname_java) in
match typ.desc with Tstruct _ -> mk (Tptr (typ, Pk_pointer)) | _ -> typ
module Fieldname = struct
type clang_field_info = {class_name: Name.t; field_name: string} [@@deriving compare]

@ -258,19 +258,19 @@ type typ = t
module Procname : sig
(** Module for Procedure Names. *)
type method_kind =
| Non_Static
(** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static (** in Java, procedures called with invokestatic *)
(** Type of java procedure names. *)
module Java : sig
type kind =
| Non_Static
(** in Java, procedures called with invokevirtual, invokespecial, and invokeinterface *)
| Static (** in Java, procedures called with invokestatic *)
type t [@@deriving compare]
(** e.g. ("", "int") for primitive types or ("java.io", "PrintWriter") for objects *)
type java_type = string option * string
val make : Name.t -> java_type option -> string -> java_type list -> method_kind -> t
val make : Name.t -> java_type option -> string -> java_type list -> kind -> t
(** Create a Java procedure name from its
class_name method_name args_type_name return_type_name method_kind. *)
@ -300,6 +300,38 @@ module Procname : sig
val replace_method : t -> string -> t
(** Replace the method name of an existing java procname. *)
val get_return_typ : t -> typ
(** Return the return type of [pname_java]. return Tvoid if there's no return type *)
val is_access_method : t -> bool
(** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. *)
val is_autogen_method : t -> bool
(** Check if the procedure name is of an auto-generated method containing '$'. *)
val is_anonymous_inner_class_constructor : t -> bool
(** Check if the procedure name is an anonymous inner class constructor. *)
val is_close : t -> bool
(** Check if the method name is "close". *)
val is_static : t -> bool
(** Check if the java procedure is static. *)
val is_vararg : t -> bool
(** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. *)
val is_lambda : t -> bool
(** Check if the proc name comes from a lambda expression *)
val is_generated : t -> bool
(** Check if the proc name comes from generated code *)
val is_class_initializer : t -> bool
(** Check if this is a class initializer. *)
end
(** Type of c procedure names. *)
@ -435,35 +467,6 @@ module Procname : sig
val objc_method_kind_of_bool : bool -> objc_cpp_method_kind
(** Create ObjC method type from a bool is_instance. *)
val java_is_access_method : t -> bool
(** Check if the procedure name is an acess method (e.g. access$100 used to
access private members from a nested class. *)
val java_is_autogen_method : t -> bool
(** Check if the procedure name is of an auto-generated method containing '$'. *)
val java_is_anonymous_inner_class_constructor : t -> bool
(** Check if the procedure name is an anonymous inner class constructor. *)
val java_is_close : t -> bool
(** Check if the method name is "close". *)
val java_is_static : t -> bool
(** Check if the java procedure is static. *)
val java_is_vararg : t -> bool
(** Check if the proc name has the type of a java vararg.
Note: currently only checks that the last argument has type Object[]. *)
val java_is_lambda : t -> bool
(** Check if the proc name comes from a lambda expression *)
val java_is_generated : t -> bool
(** Check if the proc name comes from generated code *)
val is_class_initializer : t -> bool
(** Check if this is a class initializer. *)
val is_infer_undefined : t -> bool
(** Check if this is a special Infer undefined procedure. *)
@ -500,9 +503,6 @@ module Procname : sig
(** get qualifiers of a class owning objc/C++ method *)
end
val java_proc_return_typ : Procname.Java.t -> t
(** Return the return type of [pname_java]. *)
module Fieldname : sig
(** Names for fields of class/struct/union *)
type t [@@deriving compare]

@ -1083,7 +1083,7 @@ let report_runtime_exceptions tenv pdesc summary =
&&
match pname with
| Typ.Procname.Java pname_java ->
Typ.Procname.java_is_static pname
Typ.Procname.Java.is_static pname_java
&& String.equal (Typ.Procname.Java.get_method pname_java) "main"
| _ ->
false

@ -904,7 +904,12 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
in
let is_synchronized_on_class guarded_by_str =
guarded_by_str_is_current_class guarded_by_str pname && Procdesc.is_java_synchronized pdesc
&& Typ.Procname.java_is_static pname
&&
match pname with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_static java_pname
| _ ->
false
in
let warn accessed_fld guarded_by_str =
let loc = State.get_loc () in
@ -929,8 +934,14 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
( guarded_by_str_is_current_class_this guarded_by_str pname
|| guarded_by_str_is_super_class_this guarded_by_str pname )
&& Procdesc.is_java_synchronized pdesc
|| guarded_by_str_is_current_class guarded_by_str pname
&& Procdesc.is_java_synchronized pdesc && Typ.Procname.java_is_static pname
|| ( guarded_by_str_is_current_class guarded_by_str pname
&& Procdesc.is_java_synchronized pdesc
&&
match pname with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_static java_pname
| _ ->
false )
|| (* or the prop says we already have the lock *)
List.exists
~f:(function Sil.Apred (Alocked, _) -> true | _ -> false)
@ -972,7 +983,12 @@ let add_guarded_by_constraints tenv prop lexp pdesc =
in
Procdesc.get_access pdesc <> PredSymb.Private
&& not (Annotations.pdesc_return_annot_ends_with pdesc Annotations.visibleForTesting)
&& not (Typ.Procname.java_is_access_method (Procdesc.get_proc_name pdesc))
&& not
( match Procdesc.get_proc_name pdesc with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_access_method java_pname
| _ ->
false )
&& not (is_accessible_through_local_ref lexp) && not guardedby_is_self_referential
&& not (proc_has_suppress_guarded_by_annot pdesc)
in
@ -1761,10 +1777,15 @@ let rearrange ?(report_deref_errors= true) pdesc tenv lexp typ prop loc
if report_deref_errors then check_dereference_error tenv pdesc prop nlexp (State.get_loc ()) ;
let pname = Procdesc.get_proc_name pdesc in
let prop' =
if Config.csl_analysis && !Config.footprint && Typ.Procname.is_java pname
&& not (Typ.Procname.is_constructor pname || Typ.Procname.is_class_initializer pname)
then add_guarded_by_constraints tenv prop lexp pdesc
else prop
match pname with
| Typ.Procname.Java java_pname
when Config.csl_analysis && !Config.footprint
&& not
( Typ.Procname.is_constructor pname
|| Typ.Procname.Java.is_class_initializer java_pname ) ->
add_guarded_by_constraints tenv prop lexp pdesc
| _ ->
prop
in
match Prop.prop_iter_create prop' with
| None ->

@ -38,13 +38,19 @@ let log_issue_from_errlog err_kind err_log ?loc ?node_id ?session ?ltr ?linters_
let log_issue_from_summary err_kind summary ?loc ?node_id ?session ?ltr ?linters_def_file ?doc_url
?access exn =
let is_generated_method = Typ.Procname.java_is_generated (Specs.get_proc_name summary) in
let is_java_generated_method =
match Specs.get_proc_name summary with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_generated java_pname
| _ ->
false
in
let should_suppress_lint =
Config.curr_language_is Config.Java
&& Annotations.ia_is_suppress_lint
(fst (Specs.get_attributes summary).ProcAttributes.method_annotation)
in
if should_suppress_lint || is_generated_method then () (* Skip the reporting *)
if should_suppress_lint || is_java_generated_method then () (* Skip the reporting *)
else
let err_log = Specs.get_err_log summary in
log_issue_from_errlog err_kind err_log ?loc ?node_id ?session ?ltr ?linters_def_file ?doc_url

@ -723,7 +723,7 @@ let call_constructor_url_update_args pname actual_params =
Typ.Procname.Java
(Typ.Procname.Java.make
(Typ.Name.Java.from_string "java.net.URL")
None "<init>" [(Some "java.lang", "String")] Typ.Procname.Non_Static)
None "<init>" [(Some "java.lang", "String")] Typ.Procname.Java.Non_Static)
in
if Typ.Procname.equal url_pname pname then
match actual_params with
@ -1186,7 +1186,7 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
in
match resolved_summary_opt with
| None ->
let ret_typ = Typ.java_proc_return_typ callee_pname_java in
let ret_typ = Typ.Procname.Java.get_return_typ callee_pname_java in
let ret_annots = load_ret_annots callee_pname in
exec_skip_call ~reason:"unknown method" resolved_pname ret_annots ret_typ
| Some resolved_summary ->
@ -1211,7 +1211,7 @@ let rec sym_exec tenv current_pdesc instr_ (prop_: Prop.normal Prop.t) path
in
match Ondemand.analyze_proc_name current_pdesc pname with
| None ->
let ret_typ = Typ.java_proc_return_typ callee_pname_java in
let ret_typ = Typ.Procname.Java.get_return_typ callee_pname_java in
let ret_annots = load_ret_annots callee_pname in
exec_skip_call ~reason:"unknown method" ret_annots ret_typ
| Some callee_summary ->

@ -35,11 +35,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let is_non_objc_instance_method callee_pname =
if Typ.Procname.is_java callee_pname then not (Typ.Procname.java_is_static callee_pname)
else
Option.exists
~f:(fun attributes -> attributes.ProcAttributes.is_cpp_instance_method)
(Specs.proc_resolve_attributes callee_pname)
match callee_pname with
| Typ.Procname.Java java_pname ->
not (Typ.Procname.Java.is_static java_pname)
| _ ->
Option.exists
~f:(fun attributes -> attributes.ProcAttributes.is_cpp_instance_method)
(Specs.proc_resolve_attributes callee_pname)
let is_objc_instance_method callee_pname =

@ -854,8 +854,14 @@ let pdesc_is_assumed_thread_safe pdesc tenv =
find more bugs. this is just a temporary measure to avoid obvious false positives *)
let should_analyze_proc pdesc tenv =
let pn = Procdesc.get_proc_name pdesc in
not (Typ.Procname.is_class_initializer pn) && not (FbThreadSafety.is_logging_method pn)
&& not (pdesc_is_assumed_thread_safe pdesc tenv) && not (RacerDConfig.Models.should_skip pn)
not
( match pn with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_class_initializer java_pname
| _ ->
false )
&& not (FbThreadSafety.is_logging_method pn) && not (pdesc_is_assumed_thread_safe pdesc tenv)
&& not (RacerDConfig.Models.should_skip pn)
let get_current_class_and_threadsafe_superclasses tenv pname =
@ -1277,7 +1283,12 @@ let make_read_write_race_description ~read_is_sync (conflict: reported_access) p
let should_report_on_proc proc_desc tenv =
let proc_name = Procdesc.get_proc_name proc_desc in
is_thread_safe_method proc_name tenv
|| not (Typ.Procname.java_is_autogen_method proc_name)
|| not
( match proc_name with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_autogen_method java_pname
| _ ->
false )
&& Procdesc.get_access proc_desc <> PredSymb.Private
&& not (Annotations.pdesc_return_annot_ends_with proc_desc Annotations.visibleForTesting)

@ -326,7 +326,11 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
let proc_name = Procdesc.get_proc_name proc_desc in
let calls_this = ref false in
let filter_special_cases () =
if Typ.Procname.java_is_access_method proc_name
if ( match proc_name with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_access_method java_pname
| _ ->
false )
|| (Specs.pdesc_resolve_attributes proc_desc).ProcAttributes.is_bridge_method
then None
else

@ -202,7 +202,12 @@ let check_field_assignment tenv find_canonical_duplicate curr_pdesc node instr_r
match t_ia_opt with Some (_, ia) -> Annotations.ia_is_mutable ia | _ -> false
in
Config.eradicate_field_not_mutable && not (Typ.Procname.is_constructor curr_pname)
&& not (Typ.Procname.is_class_initializer curr_pname) && not (field_is_mutable ())
&& ( match curr_pname with
| Typ.Procname.Java java_pname ->
not (Typ.Procname.Java.is_class_initializer java_pname)
| _ ->
true )
&& not (field_is_mutable ())
in
( if should_report_nullable || should_report_absent then
let ann =
@ -311,7 +316,11 @@ let check_return_annotation tenv find_canonical_duplicate curr_pdesc ret_range
match ret_range with
(* Disables the warnings since it is not clear how to annotate the return value of lambdas *)
| Some _
when Typ.Procname.java_is_lambda curr_pname ->
when match curr_pname with
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_lambda java_pname
| _ ->
false ->
()
| Some (_, final_ta, _) ->
let final_nullable = TypeAnnotation.get_value AnnotatedSignature.Nullable final_ta in

@ -546,13 +546,14 @@ let typecheck_instr tenv ext calls_this checks (node: Procdesc.Node.t) idenv get
List.mapi
~f:(fun i (_, typ) ->
let arg =
if Int.equal i 0 && not (Typ.Procname.java_is_static callee_pname) then "this"
if Int.equal i 0 && not (Typ.Procname.Java.is_static callee_pname_java) then
"this"
else Printf.sprintf "arg%d" i
in
(Mangled.from_string arg, typ) )
etl_
in
let ret_type = Typ.java_proc_return_typ callee_pname_java in
let ret_type = Typ.Procname.Java.get_return_typ callee_pname_java in
let proc_attributes =
{(ProcAttributes.default callee_pname) with ProcAttributes.formals; ret_type}
in
@ -572,7 +573,7 @@ let typecheck_instr tenv ext calls_this checks (node: Procdesc.Node.t) idenv get
drop_unchecked_signature_params callee_attributes annotated_signature
in
let is_anonymous_inner_class_constructor =
Typ.Procname.java_is_anonymous_inner_class_constructor callee_pname
Typ.Procname.Java.is_anonymous_inner_class_constructor callee_pname_java
in
let do_return (ret_ta, ret_typ) loc' typestate' =
let mk_return_range () = (ret_typ, ret_ta, [loc']) in
@ -858,7 +859,7 @@ let typecheck_instr tenv ext calls_this checks (node: Procdesc.Node.t) idenv get
(Models.get_check_not_null_parameter callee_pname)
~is_vararg:false typestate2
else if has_method callee_pname "checkNotNull"
&& Typ.Procname.java_is_vararg callee_pname
&& Typ.Procname.Java.is_vararg callee_pname_java
then
let last_parameter = List.length call_params in
do_preconditions_check_not_null last_parameter ~is_vararg:true typestate2

@ -110,9 +110,9 @@ let formals_from_signature program tenv cn ms kind =
in
let init_arg_list =
match kind with
| Typ.Procname.Static ->
| Typ.Procname.Java.Static ->
[]
| Typ.Procname.Non_Static ->
| Typ.Procname.Java.Non_Static ->
[(JConfig.this, JTransType.get_class_type program tenv cn)]
in
List.rev (List.fold ~f:collect ~init:init_arg_list (JBasics.ms_args ms))
@ -650,6 +650,12 @@ let method_invocation (context: JContext.t) loc pc var_opt cn ms sil_obj_opt exp
let sil_var = JContext.set_pvar context var return_type in
call_ret_instrs sil_var
in
let is_close = function
| Typ.Procname.Java java_pname ->
Typ.Procname.Java.is_close java_pname
| _ ->
false
in
let instrs =
match call_args with
(* modeling a class bypasses the treatment of Closeable *)
@ -668,7 +674,7 @@ let method_invocation (context: JContext.t) loc pc var_opt cn ms sil_obj_opt exp
call_instrs @ [set_file_attr]
(* remove file attribute when calling the close method of a subtype of Closeable *)
| [exp]
when Typ.Procname.java_is_close callee_procname ->
when is_close callee_procname ->
let set_mem_attr =
let set_builtin = Exp.Const (Const.Cfun BuiltinDecl.__set_mem_attribute) in
Sil.Call (None, set_builtin, [exp], loc, CallFlags.default)
@ -891,7 +897,7 @@ let instruction (context: JContext.t) pc instr : translation =
let constr_procname, call_instrs =
let ret_opt = Some (Exp.Var ret_id, class_type) in
method_invocation context loc pc None cn constr_ms ret_opt constr_arg_list I_Special
Typ.Procname.Non_Static
Typ.Procname.Java.Non_Static
in
let pvar = JContext.set_pvar context var class_type in
let set_instr = Sil.Store (Exp.Lvar pvar, class_type, Exp.Var ret_id, loc) in
@ -929,7 +935,7 @@ let instruction (context: JContext.t) pc instr : translation =
in
let callee_procname, call_instrs =
method_invocation context loc pc var_opt cn ms sil_obj_opt args I_Static
Typ.Procname.Static
Typ.Procname.Java.Static
in
let node_kind = create_node_kind callee_procname in
let call_node = create_node node_kind (instrs @ call_instrs) in
@ -944,7 +950,7 @@ let instruction (context: JContext.t) pc instr : translation =
let callee_procname, call_instrs =
let ret_opt = Some (sil_obj_expr, sil_obj_type) in
method_invocation context loc pc var_opt cn ms ret_opt args invoke_kind
Typ.Procname.Non_Static
Typ.Procname.Java.Non_Static
in
let node_kind = create_node_kind callee_procname in
let call_node = create_node node_kind (instrs @ call_instrs) in
@ -978,7 +984,7 @@ let instruction (context: JContext.t) pc instr : translation =
let instrs, sil_obj_expr, sil_obj_type = expression context pc obj in
let callee_procname, call_instrs =
method_invocation context loc pc var_opt cn ms (Some (sil_obj_expr, sil_obj_type)) args
I_Special Typ.Procname.Non_Static
I_Special Typ.Procname.Java.Non_Static
in
let node_kind = create_node_kind callee_procname in
let call_node = create_node node_kind (instrs @ call_instrs) in
@ -1022,7 +1028,7 @@ let instruction (context: JContext.t) pc instr : translation =
let _, call_instrs =
let ret_opt = Some (Exp.Var ret_id, class_type) in
method_invocation context loc pc None npe_cn constr_ms ret_opt [] I_Special
Typ.Procname.Static
Typ.Procname.Java.Static
in
let sil_exn = Exp.Exn (Exp.Var ret_id) in
let set_instr = Sil.Store (Exp.Lvar ret_var, ret_type, sil_exn, loc) in
@ -1079,7 +1085,7 @@ let instruction (context: JContext.t) pc instr : translation =
let constr_ms = JBasics.make_ms JConfig.constructor_name [] None in
let _, call_instrs =
method_invocation context loc pc None out_of_bound_cn constr_ms
(Some (Exp.Var ret_id, class_type)) [] I_Special Typ.Procname.Static
(Some (Exp.Var ret_id, class_type)) [] I_Special Typ.Procname.Java.Static
in
let sil_exn = Exp.Exn (Exp.Var ret_id) in
let set_instr = Sil.Store (Exp.Lvar ret_var, ret_type, sil_exn, loc) in
@ -1124,7 +1130,7 @@ let instruction (context: JContext.t) pc instr : translation =
let constr_ms = JBasics.make_ms JConfig.constructor_name [] None in
let _, call_instrs =
method_invocation context loc pc None cce_cn constr_ms
(Some (Exp.Var ret_id, class_type)) [] I_Special Typ.Procname.Static
(Some (Exp.Var ret_id, class_type)) [] I_Special Typ.Procname.Java.Static
in
let sil_exn = Exp.Exn (Exp.Var ret_id) in
let set_instr = Sil.Store (Exp.Lvar ret_var, ret_type, sil_exn, loc) in

@ -217,7 +217,7 @@ let method_signature_names ms =
let get_method_kind m =
if Javalib.is_static_method m then Typ.Procname.Static else Typ.Procname.Non_Static
if Javalib.is_static_method m then Typ.Procname.Java.Static else Typ.Procname.Java.Non_Static
let get_method_procname cn ms method_kind =

@ -12,10 +12,10 @@ open! IStd
open Javalib_pack
open Sawja_pack
val get_method_kind : JCode.jcode Javalib.jmethod -> Typ.Procname.method_kind
val get_method_kind : JCode.jcode Javalib.jmethod -> Typ.Procname.Java.kind
val get_method_procname :
JBasics.class_name -> JBasics.method_signature -> Typ.Procname.method_kind -> Typ.Procname.t
JBasics.class_name -> JBasics.method_signature -> Typ.Procname.Java.kind -> Typ.Procname.t
(** returns a procedure name based on the class name and the method's signature. *)
val translate_method_name : JCode.jcode Javalib.jmethod -> Typ.Procname.t

@ -41,9 +41,9 @@ include TaintAnalysis.Make (struct
false
in
match pname with
| Typ.Procname.Java java_pname as pname
| Typ.Procname.Java java_pname
-> (
let is_static = Typ.Procname.java_is_static pname in
let is_static = Typ.Procname.Java.is_static java_pname in
match
( Typ.Procname.Java.get_class_name java_pname
, Typ.Procname.Java.get_method java_pname

@ -278,108 +278,110 @@ module SinkKind = struct
let get pname actuals tenv =
(* taint all the inputs of [pname]. for non-static procedures, taints the "this" parameter only
if [taint_this] is true. *)
let taint_all ?(taint_this= false) kind =
let actuals_to_taint, offset =
if Typ.Procname.java_is_static pname || taint_this then (actuals, 0)
else (List.tl_exn actuals, 1)
in
let indexes =
IntSet.of_list (List.mapi ~f:(fun param_num _ -> param_num + offset) actuals_to_taint)
in
Some (kind, indexes)
in
(* taint the nth non-"this" parameter (0-indexed) *)
let taint_nth n kind =
let first_index = if Typ.Procname.java_is_static pname then n else n + 1 in
if first_index < List.length actuals then Some (kind, IntSet.singleton first_index) else None
in
match pname with
| Typ.Procname.Java java_pname -> (
match
(Typ.Procname.Java.get_class_name java_pname, Typ.Procname.Java.get_method java_pname)
with
| "android.text.Html", "fromHtml" ->
taint_nth 0 HTML
| "android.util.Log", ("e" | "println" | "w" | "wtf") ->
taint_all Logging
| "java.io.File", "<init>"
| "java.nio.file.FileSystem", "getPath"
| "java.nio.file.Paths", "get" ->
taint_all CreateFile
| "java.io.ObjectInputStream", "<init>" ->
taint_all Deserialization
| "com.facebook.infer.builtins.InferTaint", "inferSensitiveSink" ->
taint_nth 0 Other
| class_name, method_name ->
let taint_matching_supertype typename =
match (Typ.Name.name typename, method_name) with
| "android.app.Activity", ("startActivityFromChild" | "startActivityFromFragment") ->
taint_nth 1 StartComponent
| "android.app.Activity", "startIntentSenderForResult" ->
taint_nth 2 StartComponent
| "android.app.Activity", "startIntentSenderFromChild" ->
taint_nth 3 StartComponent
| ( "android.content.Context"
, ( "bindService"
| "sendBroadcast"
| "sendBroadcastAsUser"
| "sendOrderedBroadcast"
| "sendOrderedBroadcastAsUser"
| "sendStickyBroadcast"
| "sendStickyBroadcastAsUser"
| "sendStickyOrderedBroadcast"
| "sendStickyOrderedBroadcastAsUser"
| "startActivities"
| "startActivity"
| "startActivityForResult"
| "startActivityIfNeeded"
| "startNextMatchingActivity"
| "startService"
| "stopService" ) ) ->
taint_nth 0 StartComponent
| "android.content.Context", "startIntentSender" ->
taint_nth 1 StartComponent
| ( "android.content.Intent"
, ( "parseUri"
| "getIntent"
| "getIntentOld"
| "setComponent"
| "setData"
| "setDataAndNormalize"
| "setDataAndType"
| "setDataAndTypeAndNormalize"
| "setPackage" ) ) ->
taint_nth 0 CreateIntent
| "android.content.Intent", "setClassName" ->
taint_all CreateIntent
| ( "android.webkit.WebView"
, ( "evaluateJavascript"
| "loadData"
| "loadDataWithBaseURL"
| "loadUrl"
| "postUrl"
| "postWebMessage" ) ) ->
taint_all JavaScript
| class_name, method_name ->
(* check the list of externally specified sinks *)
let procedure = class_name ^ "." ^ method_name in
List.find_map
~f:(fun (procedure_regex, kind, index) ->
if Str.string_match procedure_regex procedure 0 then
let kind = of_string kind in
try
let n = int_of_string index in
taint_nth n kind
with Failure _ ->
(* couldn't parse the index, just taint everything *)
taint_all kind
else None )
external_sinks
| Typ.Procname.Java java_pname
-> (
(* taint all the inputs of [pname]. for non-static procedures, taints the "this" parameter
only if [taint_this] is true. *)
let taint_all ?(taint_this= false) kind =
let actuals_to_taint, offset =
if Typ.Procname.Java.is_static java_pname || taint_this then (actuals, 0)
else (List.tl_exn actuals, 1)
in
let indexes =
IntSet.of_list (List.mapi ~f:(fun param_num _ -> param_num + offset) actuals_to_taint)
in
PatternMatch.supertype_find_map_opt tenv taint_matching_supertype
(Typ.Name.Java.from_string class_name) )
Some (kind, indexes)
in
(* taint the nth non-"this" parameter (0-indexed) *)
let taint_nth n kind =
let first_index = if Typ.Procname.Java.is_static java_pname then n else n + 1 in
if first_index < List.length actuals then Some (kind, IntSet.singleton first_index)
else None
in
match
(Typ.Procname.Java.get_class_name java_pname, Typ.Procname.Java.get_method java_pname)
with
| "android.text.Html", "fromHtml" ->
taint_nth 0 HTML
| "android.util.Log", ("e" | "println" | "w" | "wtf") ->
taint_all Logging
| "java.io.File", "<init>"
| "java.nio.file.FileSystem", "getPath"
| "java.nio.file.Paths", "get" ->
taint_all CreateFile
| "java.io.ObjectInputStream", "<init>" ->
taint_all Deserialization
| "com.facebook.infer.builtins.InferTaint", "inferSensitiveSink" ->
taint_nth 0 Other
| class_name, method_name ->
let taint_matching_supertype typename =
match (Typ.Name.name typename, method_name) with
| "android.app.Activity", ("startActivityFromChild" | "startActivityFromFragment") ->
taint_nth 1 StartComponent
| "android.app.Activity", "startIntentSenderForResult" ->
taint_nth 2 StartComponent
| "android.app.Activity", "startIntentSenderFromChild" ->
taint_nth 3 StartComponent
| ( "android.content.Context"
, ( "bindService"
| "sendBroadcast"
| "sendBroadcastAsUser"
| "sendOrderedBroadcast"
| "sendOrderedBroadcastAsUser"
| "sendStickyBroadcast"
| "sendStickyBroadcastAsUser"
| "sendStickyOrderedBroadcast"
| "sendStickyOrderedBroadcastAsUser"
| "startActivities"
| "startActivity"
| "startActivityForResult"
| "startActivityIfNeeded"
| "startNextMatchingActivity"
| "startService"
| "stopService" ) ) ->
taint_nth 0 StartComponent
| "android.content.Context", "startIntentSender" ->
taint_nth 1 StartComponent
| ( "android.content.Intent"
, ( "parseUri"
| "getIntent"
| "getIntentOld"
| "setComponent"
| "setData"
| "setDataAndNormalize"
| "setDataAndType"
| "setDataAndTypeAndNormalize"
| "setPackage" ) ) ->
taint_nth 0 CreateIntent
| "android.content.Intent", "setClassName" ->
taint_all CreateIntent
| ( "android.webkit.WebView"
, ( "evaluateJavascript"
| "loadData"
| "loadDataWithBaseURL"
| "loadUrl"
| "postUrl"
| "postWebMessage" ) ) ->
taint_all JavaScript
| class_name, method_name ->
(* check the list of externally specified sinks *)
let procedure = class_name ^ "." ^ method_name in
List.find_map
~f:(fun (procedure_regex, kind, index) ->
if Str.string_match procedure_regex procedure 0 then
let kind = of_string kind in
try
let n = int_of_string index in
taint_nth n kind
with Failure _ ->
(* couldn't parse the index, just taint everything *)
taint_all kind
else None )
external_sinks
in
PatternMatch.supertype_find_map_opt tenv taint_matching_supertype
(Typ.Name.Java.from_string class_name) )
| pname when BuiltinDecl.is_declared pname ->
None
| pname ->

Loading…
Cancel
Save