From f7c415f7ae72ad64ee05e59f96d73fa2238412e8 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Thu, 18 Jan 2018 14:25:31 -0800 Subject: [PATCH] [cleanup] restrict Java-specific utility functions to Typ.Procname.Java.t's Reviewed By: jeremydubreil Differential Revision: D6740465 fbshipit-source-id: 4ad717b --- infer/src/IR/Cfg.ml | 4 +- infer/src/IR/Typ.ml | 188 +++++++++------------- infer/src/IR/Typ.mli | 76 ++++----- infer/src/backend/interproc.ml | 2 +- infer/src/backend/rearrange.ml | 37 ++++- infer/src/backend/reporting.ml | 10 +- infer/src/backend/symExec.ml | 6 +- infer/src/checkers/NullabilityCheck.ml | 12 +- infer/src/concurrency/RacerD.ml | 17 +- infer/src/eradicate/eradicate.ml | 6 +- infer/src/eradicate/eradicateChecks.ml | 13 +- infer/src/eradicate/typeCheck.ml | 9 +- infer/src/java/jTrans.ml | 26 +-- infer/src/java/jTransType.ml | 2 +- infer/src/java/jTransType.mli | 4 +- infer/src/quandary/JavaTaintAnalysis.ml | 4 +- infer/src/quandary/JavaTrace.ml | 202 ++++++++++++------------ 17 files changed, 320 insertions(+), 298 deletions(-) diff --git a/infer/src/IR/Cfg.ml b/infer/src/IR/Cfg.ml index 69d39eff4..9e383f8cc 100644 --- a/infer/src/IR/Cfg.ml +++ b/infer/src/IR/Cfg.ml @@ -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 diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 0785411c2..235535633 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -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 "" + + 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 "" - | _ -> - 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] diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index b8e243f6c..d11a23be1 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -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] diff --git a/infer/src/backend/interproc.ml b/infer/src/backend/interproc.ml index 7baee8b49..55795092f 100644 --- a/infer/src/backend/interproc.ml +++ b/infer/src/backend/interproc.ml @@ -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 diff --git a/infer/src/backend/rearrange.ml b/infer/src/backend/rearrange.ml index 4e52d71e4..0a0adff5d 100644 --- a/infer/src/backend/rearrange.ml +++ b/infer/src/backend/rearrange.ml @@ -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 -> diff --git a/infer/src/backend/reporting.ml b/infer/src/backend/reporting.ml index 953ceacd4..170133b59 100644 --- a/infer/src/backend/reporting.ml +++ b/infer/src/backend/reporting.ml @@ -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 diff --git a/infer/src/backend/symExec.ml b/infer/src/backend/symExec.ml index ba560d58a..a0727c31f 100644 --- a/infer/src/backend/symExec.ml +++ b/infer/src/backend/symExec.ml @@ -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 "" [(Some "java.lang", "String")] Typ.Procname.Non_Static) + None "" [(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 -> diff --git a/infer/src/checkers/NullabilityCheck.ml b/infer/src/checkers/NullabilityCheck.ml index c0f0ea2aa..997081440 100644 --- a/infer/src/checkers/NullabilityCheck.ml +++ b/infer/src/checkers/NullabilityCheck.ml @@ -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 = diff --git a/infer/src/concurrency/RacerD.ml b/infer/src/concurrency/RacerD.ml index 0dd0e37c5..8cfe4ce54 100644 --- a/infer/src/concurrency/RacerD.ml +++ b/infer/src/concurrency/RacerD.ml @@ -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) diff --git a/infer/src/eradicate/eradicate.ml b/infer/src/eradicate/eradicate.ml index 891249d5a..a99ef8b93 100644 --- a/infer/src/eradicate/eradicate.ml +++ b/infer/src/eradicate/eradicate.ml @@ -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 diff --git a/infer/src/eradicate/eradicateChecks.ml b/infer/src/eradicate/eradicateChecks.ml index d52d078df..102065a44 100644 --- a/infer/src/eradicate/eradicateChecks.ml +++ b/infer/src/eradicate/eradicateChecks.ml @@ -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 diff --git a/infer/src/eradicate/typeCheck.ml b/infer/src/eradicate/typeCheck.ml index 7180fe2b2..33ca12f1e 100644 --- a/infer/src/eradicate/typeCheck.ml +++ b/infer/src/eradicate/typeCheck.ml @@ -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 diff --git a/infer/src/java/jTrans.ml b/infer/src/java/jTrans.ml index c80aa2eae..3bf81e5ce 100644 --- a/infer/src/java/jTrans.ml +++ b/infer/src/java/jTrans.ml @@ -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 diff --git a/infer/src/java/jTransType.ml b/infer/src/java/jTransType.ml index 6a6e55e66..4b2e2b5df 100644 --- a/infer/src/java/jTransType.ml +++ b/infer/src/java/jTransType.ml @@ -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 = diff --git a/infer/src/java/jTransType.mli b/infer/src/java/jTransType.mli index e1c1faf25..8897a1aea 100644 --- a/infer/src/java/jTransType.mli +++ b/infer/src/java/jTransType.mli @@ -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 diff --git a/infer/src/quandary/JavaTaintAnalysis.ml b/infer/src/quandary/JavaTaintAnalysis.ml index b4cb90222..e7215e928 100644 --- a/infer/src/quandary/JavaTaintAnalysis.ml +++ b/infer/src/quandary/JavaTaintAnalysis.ml @@ -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 diff --git a/infer/src/quandary/JavaTrace.ml b/infer/src/quandary/JavaTrace.ml index 6c584316a..8255c5773 100644 --- a/infer/src/quandary/JavaTrace.ml +++ b/infer/src/quandary/JavaTrace.ml @@ -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", "" - | "java.nio.file.FileSystem", "getPath" - | "java.nio.file.Paths", "get" -> - taint_all CreateFile - | "java.io.ObjectInputStream", "" -> - 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", "" + | "java.nio.file.FileSystem", "getPath" + | "java.nio.file.Paths", "get" -> + taint_all CreateFile + | "java.io.ObjectInputStream", "" -> + 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 ->