From 181959216bf4e5bb34bd4de6d4c196136e1b21f9 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Fri, 17 Nov 2017 12:55:37 -0800 Subject: [PATCH] [cleanup] remove harness-related code Reviewed By: jeremydubreil Differential Revision: D6359547 fbshipit-source-id: 3cb467a --- Makefile | 2 +- infer/src/.merlin | 1 - infer/src/base/Config.ml | 8 - infer/src/base/Config.mli | 2 - infer/src/checkers/androidFramework.ml | 55 +++ .../androidFramework.mli | 8 - infer/src/harness/androidFramework.ml | 129 ------- infer/src/harness/harness.ml | 72 ---- infer/src/harness/harness.mli | 15 - infer/src/harness/inhabit.ml | 315 ------------------ infer/src/harness/inhabit.mli | 18 - infer/src/java/jMain.ml | 7 +- infer/src/jbuild.in | 1 - .../java/harness/BasicHarnessActivity.java | 41 --- .../tests/codetoanalyze/java/harness/Makefile | 16 - .../codetoanalyze/java/harness/MyView.java | 19 -- .../java/harness/TrickyParamsActivity.java | 40 --- .../codetoanalyze/java/harness/issues.exp | 1 - 18 files changed, 59 insertions(+), 691 deletions(-) create mode 100644 infer/src/checkers/androidFramework.ml rename infer/src/{harness => checkers}/androidFramework.mli (74%) delete mode 100644 infer/src/harness/androidFramework.ml delete mode 100644 infer/src/harness/harness.ml delete mode 100644 infer/src/harness/harness.mli delete mode 100644 infer/src/harness/inhabit.ml delete mode 100644 infer/src/harness/inhabit.mli delete mode 100644 infer/tests/codetoanalyze/java/harness/BasicHarnessActivity.java delete mode 100644 infer/tests/codetoanalyze/java/harness/Makefile delete mode 100644 infer/tests/codetoanalyze/java/harness/MyView.java delete mode 100644 infer/tests/codetoanalyze/java/harness/TrickyParamsActivity.java delete mode 100644 infer/tests/codetoanalyze/java/harness/issues.exp diff --git a/Makefile b/Makefile index 8590f598e..c6af1b47d 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ BUILD_SYSTEMS_TESTS += \ DIRECT_TESTS += \ java_checkers java_eradicate java_infer java_lab java_tracing java_quandary \ - java_racerd java_crashcontext java_harness + java_racerd java_crashcontext ifneq ($(ANT),no) BUILD_SYSTEMS_TESTS += ant endif diff --git a/infer/src/.merlin b/infer/src/.merlin index 60c609a0c..7e2c99b41 100644 --- a/infer/src/.merlin +++ b/infer/src/.merlin @@ -78,7 +78,6 @@ S clang S concurrency S eradicate S facebook -S harness S integration S istd S java diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index ddd79d111..d044aed40 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -699,12 +699,6 @@ and analyzer = x) ~symbols:string_to_analyzer - -and android_harness = - CLOpt.mk_bool ~deprecated:["harness"] ~long:"android-harness" - "(Experimental) Create harness to detect issues involving the Android lifecycle" - - and ( annotation_reachability , biabduction , bufferoverrun @@ -2363,8 +2357,6 @@ and current_to_previous_script = !current_to_previous_script and crashcontext = !crashcontext -and create_harness = !android_harness - and cxx = !cxx and cxx_infer_headers = !cxx_infer_headers diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 321519118..866b35b6f 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -353,8 +353,6 @@ val continue_capture : bool val crashcontext : bool -val create_harness : bool - val current_to_previous_script : string option val cxx : bool diff --git a/infer/src/checkers/androidFramework.ml b/infer/src/checkers/androidFramework.ml new file mode 100644 index 000000000..f49699fa0 --- /dev/null +++ b/infer/src/checkers/androidFramework.ml @@ -0,0 +1,55 @@ +(* + * Copyright (c) 2013 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + *) + +open! IStd +module L = Logging +module F = Format + +(** Android lifecycle types and their lifecycle methods that are called by the framework *) + +let on_destroy = "onDestroy" + +let on_destroy_view = "onDestroyView" + +let drawable_prefix = "R$drawable" + +(** return true if [pname] is a special lifecycle cleanup method *) +let is_destroy_method pname = + match pname with + | Typ.Procname.Java pname_java -> + let method_name = Typ.Procname.java_get_method pname_java in + String.equal method_name on_destroy || String.equal method_name on_destroy_view + | _ -> + false + + +let is_subtype_package_class tenv tname package classname = + PatternMatch.is_subtype tenv tname (Typ.Name.Java.from_package_class package classname) + + +let is_autocloseable tenv tname = is_subtype_package_class tenv tname "java.lang" "AutoCloseable" + +let is_context tenv tname = is_subtype_package_class tenv tname "android.content" "Context" + +let is_application tenv tname = is_subtype_package_class tenv tname "android.app" "Application" + +let is_activity tenv tname = is_subtype_package_class tenv tname "android.app" "Activity" + +let is_view tenv tname = is_subtype_package_class tenv tname "android.view" "View" + +let is_fragment tenv tname = + is_subtype_package_class tenv tname "android.app" "Fragment" + || is_subtype_package_class tenv tname "android.support.v4.app" "Fragment" + + +(** return true if [class_name] is the name of a class that belong to the Android framework *) +let is_android_lib_class class_name = + let class_str = Typ.Name.name class_name in + String.is_prefix ~prefix:"android" class_str || String.is_prefix ~prefix:"com.android" class_str + diff --git a/infer/src/harness/androidFramework.mli b/infer/src/checkers/androidFramework.mli similarity index 74% rename from infer/src/harness/androidFramework.mli rename to infer/src/checkers/androidFramework.mli index 9a99dd68e..8b5c8cb79 100644 --- a/infer/src/harness/androidFramework.mli +++ b/infer/src/checkers/androidFramework.mli @@ -14,9 +14,6 @@ open! IStd val drawable_prefix : string (** prefix for Drawable fields in generated resources *) -val get_lifecycles : (string * string * string list) list -(** return the complete list of (package, lifecycle_classname, lifecycle_methods) trios *) - val is_autocloseable : Tenv.t -> Typ.Name.t -> bool val is_context : Tenv.t -> Typ.Name.t -> bool @@ -36,10 +33,5 @@ val is_fragment : Tenv.t -> Typ.Name.t -> bool val is_destroy_method : Typ.Procname.t -> bool (** return true if [procname] is a special lifecycle cleanup method *) -val get_lifecycle_for_framework_typ_opt : - Tenv.t -> Typ.Name.t -> string list -> Typ.Procname.t list -(** given an Android framework type mangled string [lifecycle_typ] (e.g., android.app.Activity) - and a list of method names [lifecycle_procs_strs], get the appropriate typ and procnames *) - val is_android_lib_class : Typ.Name.t -> bool (** return true if [class_name] is the name of a class that belong to the Android framework *) diff --git a/infer/src/harness/androidFramework.ml b/infer/src/harness/androidFramework.ml deleted file mode 100644 index 36e2e6204..000000000 --- a/infer/src/harness/androidFramework.ml +++ /dev/null @@ -1,129 +0,0 @@ -(* - * Copyright (c) 2013 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -open! IStd -module L = Logging -module F = Format - -(** Android lifecycle types and their lifecycle methods that are called by the framework *) - -let on_destroy = "onDestroy" - -let on_destroy_view = "onDestroyView" - -let drawable_prefix = "R$drawable" - -(** return true if [pname] is a special lifecycle cleanup method *) -let is_destroy_method pname = - match pname with - | Typ.Procname.Java pname_java -> - let method_name = Typ.Procname.java_get_method pname_java in - String.equal method_name on_destroy || String.equal method_name on_destroy_view - | _ -> - false - - -let android_lifecycles = - let android_content = "android.content" in - let android_app = "android.app" in - let fragment_lifecycle = - [ "onInflate" - ; "onAttach" - ; "onCreate" - ; "onCreateView" - ; "onViewCreated" - ; "onActivityCreated" - ; "onViewStateRestored" - ; "onStart" - ; "onResume" - ; "onPause" - ; "onSaveInstanceState" - ; "onStop" - ; on_destroy_view - ; on_destroy - ; "onDetach" ] - in - [ (android_content, "ContentProvider", ["onCreate"]) - ; ( android_app - , "Activity" - , [ "onCreate" - ; "onStart" - ; "onRestoreInstanceState" - ; "onPostCreate" - ; "onResume" - ; "onPostResume" - ; "onCreateDescription" - ; "onSaveInstanceState" - ; "onPause" - ; "onStop" - ; on_destroy ] ) - ; ( android_app - , "Service" - , ["onCreate"; "onStart"; "onStartCommand"; "onBind"; "onUnbind"; on_destroy] ) - ; (android_content, "BroadcastReceiever", ["onReceive"]) - ; (android_app, "Fragment", fragment_lifecycle) - ; (* this is the pre-Android 3.0 Fragment type (can also be used post-3.0) *) - ("android.support.v4.app", "Fragment", fragment_lifecycle) ] - - -let is_subtype_package_class tenv tname package classname = - PatternMatch.is_subtype tenv tname (Typ.Name.Java.from_package_class package classname) - - -let is_autocloseable tenv tname = is_subtype_package_class tenv tname "java.lang" "AutoCloseable" - -let is_context tenv tname = is_subtype_package_class tenv tname "android.content" "Context" - -let is_application tenv tname = is_subtype_package_class tenv tname "android.app" "Application" - -let is_activity tenv tname = is_subtype_package_class tenv tname "android.app" "Activity" - -let is_view tenv tname = is_subtype_package_class tenv tname "android.view" "View" - -let is_fragment tenv tname = - is_subtype_package_class tenv tname "android.app" "Fragment" - || is_subtype_package_class tenv tname "android.support.v4.app" "Fragment" - - -(** return true if [class_name] is the name of a class that belong to the Android framework *) -let is_android_lib_class class_name = - let class_str = Typ.Name.name class_name in - String.is_prefix ~prefix:"android" class_str || String.is_prefix ~prefix:"com.android" class_str - - -(** given an Android framework type mangled string [lifecycle_typ] (e.g., android.app.Activity) and - a list of method names [lifecycle_procs_strs], get the appropriate typ and procnames *) -let get_lifecycle_for_framework_typ_opt tenv lifecycle_typ lifecycle_proc_strs = - match Tenv.lookup tenv lifecycle_typ with - | Some {methods} -> - (* TODO (t4645631): collect the procedures for which is_java is returning false *) - let lookup_proc lifecycle_proc = - List.find_exn - ~f:(fun decl_proc -> - match decl_proc with - | Typ.Procname.Java decl_proc_java -> - String.equal lifecycle_proc (Typ.Procname.java_get_method decl_proc_java) - | _ -> - false) - methods - in - (* convert each of the framework lifecycle proc strings to a lifecycle method procname *) - let lifecycle_procs = - List.fold - ~f:(fun lifecycle_procs lifecycle_proc_str -> - try lookup_proc lifecycle_proc_str :: lifecycle_procs with Not_found -> lifecycle_procs) - ~init:[] lifecycle_proc_strs - in - lifecycle_procs - | _ -> - [] - - -(** return the complete list of (package, lifecycle_classname, lifecycle_methods) trios *) -let get_lifecycles = android_lifecycles diff --git a/infer/src/harness/harness.ml b/infer/src/harness/harness.ml deleted file mode 100644 index f58120987..000000000 --- a/infer/src/harness/harness.ml +++ /dev/null @@ -1,72 +0,0 @@ -(* - * Copyright (c) 2013 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -open! IStd -module L = Logging -module F = Format - -(** Automatically create a harness method to exercise code under test *) - -(** if [struct_typ] is a lifecycle type, generate a list of (method call, receiver) pairs - constituting a lifecycle trace *) -let try_create_lifecycle_trace name lifecycle_name lifecycle_procs tenv = - match name with - | Typ.JavaClass _ -> - if PatternMatch.is_subtype tenv name lifecycle_name - && not (AndroidFramework.is_android_lib_class name) - then - let ptr_to_struct_typ = Some (Typ.mk (Tptr (Typ.mk (Tstruct name), Pk_pointer))) in - List.fold - ~f:(fun trace lifecycle_proc -> - (* given a lifecycle subclass T, resolve the call T.lifecycle_proc() to the procname - * that will actually be called at runtime *) - let resolved_proc = SymExec.resolve_method tenv name lifecycle_proc in - (resolved_proc, ptr_to_struct_typ) :: trace) - ~init:[] lifecycle_procs - else [] - | _ -> - [] - - -(** generate a harness for a lifecycle type in an Android application *) -let create_harness cfg cg tenv = - List.iter - ~f:(fun (pkg, clazz, lifecycle_methods) -> - let typname = Typ.Name.Java.from_package_class pkg clazz in - let framework_procs = - AndroidFramework.get_lifecycle_for_framework_typ_opt tenv typname lifecycle_methods - in - (* iterate through the type environment and generate a lifecycle harness for each - subclass of [lifecycle_typ] *) - (* TODO: instead of iterating through the type environment, interate through the types - declared in [cfg] *) - Tenv.iter - (fun name _ -> - match try_create_lifecycle_trace name typname framework_procs tenv with - | [] -> - () - | lifecycle_trace -> - let harness_procname = - let harness_cls_name = Typ.Name.name name in - let pname = - Typ.Procname.Java - (Typ.Procname.java - (Typ.Name.Java.from_string harness_cls_name) - None "InferGeneratedHarness" [] Typ.Procname.Static) - in - match pname with - | Typ.Procname.Java harness_procname -> - harness_procname - | _ -> - assert false - in - Inhabit.inhabit_trace tenv lifecycle_trace harness_procname cg cfg) - tenv) - AndroidFramework.get_lifecycles - diff --git a/infer/src/harness/harness.mli b/infer/src/harness/harness.mli deleted file mode 100644 index 02bdba805..000000000 --- a/infer/src/harness/harness.mli +++ /dev/null @@ -1,15 +0,0 @@ -(* - * Copyright (c) 2013 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -open! IStd - -(** Automatically create a harness method to exercise code under test *) - -val create_harness : Cfg.t -> Cg.t -> Tenv.t -> unit -(** Generate a harness method for exe_env and add it to the execution environment *) diff --git a/infer/src/harness/inhabit.ml b/infer/src/harness/inhabit.ml deleted file mode 100644 index f52f6119d..000000000 --- a/infer/src/harness/inhabit.ml +++ /dev/null @@ -1,315 +0,0 @@ -(* - * Copyright (c) 2013 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -open! IStd - -(** Generate a procedure that calls a given sequence of methods. Useful for harness/test - * generation. *) - -module L = Logging -module F = Format -module P = Printf -module IdSet = Ident.IdentSet -module TypSet = Typ.Set -module TypMap = Typ.Map - -type lifecycle_trace = (Typ.Procname.t * Typ.t option) list - -(** list of instrs and temporary variables created during inhabitation and a cache of types that - * have already been inhabited *) -type env = - { instrs: Sil.instr list - ; cache: Exp.t TypMap.t - ; (* set of types currently being inhabited. consult to prevent infinite recursion *) - cur_inhabiting: TypSet.t - ; pc: Location.t - ; harness_name: Typ.Procname.java } - -let procdesc_from_name cfg pname = - let pdesc_ref = ref None in - Cfg.iter_proc_desc cfg (fun cfg_pname pdesc -> - if Typ.Procname.equal cfg_pname pname then pdesc_ref := Some pdesc ) ; - !pdesc_ref - - -let formals_from_name cfg pname = - match procdesc_from_name cfg pname with Some pdesc -> Procdesc.get_formals pdesc | None -> [] - - -(** add an instruction to the env, update tmp_vars, and bump the pc *) -let env_add_instr instr env = - let incr_pc pc = {pc with Location.line= pc.Location.line + 1} in - {env with instrs= instr :: env.instrs; pc= incr_pc env.pc} - - -(** call flags for an allocation or call to a constructor *) -let cf_alloc = CallFlags.default - -let fun_exp_from_name proc_name = Exp.Const (Const.Cfun proc_name) - -let local_name_cntr = ref 0 - -let create_fresh_local_name () = - incr local_name_cntr ; - "dummy_local" ^ string_of_int !local_name_cntr - - -(** more forgiving variation of List.tl that won't raise an exception on the empty list *) -let tl_or_empty l = if List.is_empty l then l else List.tl_exn l - -let get_non_receiver_formals formals = tl_or_empty formals - -(** create Sil corresponding to x = new typ() or x = new typ[]. For ordinary allocation, sizeof_typ - * and ret_typ should be the same, but arrays are slightly odd in that sizeof_typ will have a size - * component but the size component of ret_typ is always -1. *) -let inhabit_alloc sizeof_typ sizeof_len ret_typ alloc_kind env = - let retval = Ident.create_fresh Ident.knormal in - let inhabited_exp = Exp.Var retval in - let call_instr = - let fun_new = fun_exp_from_name alloc_kind in - let sizeof_exp = - Exp.Sizeof {typ= sizeof_typ; nbytes= None; dynamic_length= sizeof_len; subtype= Subtype.exact} - in - let args = [(sizeof_exp, Typ.mk (Tptr (ret_typ, Typ.Pk_pointer)))] in - Sil.Call (Some (retval, ret_typ), fun_new, args, env.pc, cf_alloc) - in - (inhabited_exp, env_add_instr call_instr env) - - -(* TODO: this should be done in a differnt way: just make typ a param of the harness procedure *) - -(** find or create a Sil expression with type typ *) -let rec inhabit_typ tenv typ cfg env = - try (TypMap.find typ env.cache, env) with Not_found -> - let inhabit_internal typ env = - match typ.Typ.desc with - | Typ.Tptr ({desc= Tarray (inner_typ, Some _, _)}, Typ.Pk_pointer) -> - let len = Exp.Const (Const.Cint IntLit.one) in - let arr_typ = Typ.mk (Tarray (inner_typ, Some IntLit.one, None)) in - inhabit_alloc arr_typ (Some len) typ BuiltinDecl.__new_array env - | Typ.Tptr (typ, Typ.Pk_pointer) -> - (* TODO (t4575417): this case does not work correctly for enums, but they are currently - * broken in Infer anyway (see t4592290) *) - let allocated_obj_exp, env = inhabit_alloc typ None typ BuiltinDecl.__new env in - (* select methods that are constructors and won't force us into infinite recursion because - * we are already inhabiting one of their argument types *) - let get_all_suitable_constructors (typ: Typ.t) = - match typ.desc with - | Tstruct name when Typ.Name.is_class name -> ( - match Tenv.lookup tenv name with - | Some {methods} -> - let is_suitable_constructor p = - let try_get_non_receiver_formals p = - get_non_receiver_formals (formals_from_name cfg p) - in - Typ.Procname.is_constructor p - && List.for_all - ~f:(fun (_, typ) -> not (TypSet.mem typ env.cur_inhabiting)) - (try_get_non_receiver_formals p) - in - List.filter ~f:(fun p -> is_suitable_constructor p) methods - | _ -> - [] ) - | _ -> - [] - in - let env, typ_class_name = - match get_all_suitable_constructors typ with - | constructor :: _ -> - (* arbitrarily choose a constructor for typ and invoke it. eventually, we may want to - * nondeterministically call all possible constructors instead *) - let env = inhabit_constructor tenv constructor (allocated_obj_exp, typ) cfg env in - (* try to get the unqualified name as a class (e.g., Object for java.lang.Object so we - * we can use it as a descriptive local variable name in the harness *) - let typ_class_name = - match constructor with - | Typ.Procname.Java pname_java -> - Typ.Procname.java_get_simple_class_name pname_java - | _ -> - create_fresh_local_name () - in - (env, Mangled.from_string typ_class_name) - | [] -> - (env, Mangled.from_string (create_fresh_local_name ())) - in - (* add the instructions *& local = [allocated_obj_exp]; id = *& local, where local and id are - * both fresh. the only point of this is to add a descriptive local name that makes error - * reports from the harness look nicer -- it's not necessary to make symbolic execution work *) - let fresh_local_exp = - Exp.Lvar (Pvar.mk typ_class_name (Typ.Procname.Java env.harness_name)) - in - let write_to_local_instr = Sil.Store (fresh_local_exp, typ, allocated_obj_exp, env.pc) in - let env' = env_add_instr write_to_local_instr env in - let fresh_id = Ident.create_fresh Ident.knormal in - let read_from_local_instr = Sil.Load (fresh_id, fresh_local_exp, typ, env'.pc) in - (Exp.Var fresh_id, env_add_instr read_from_local_instr env') - | Typ.Tint _ -> - (Exp.Const (Const.Cint IntLit.zero), env) - | Typ.Tfloat _ -> - (Exp.Const (Const.Cfloat 0.0), env) - | _ -> - L.die InternalError "Couldn't inhabit typ: %a" (Typ.pp Pp.text) typ - in - let inhabited_exp, env' = - inhabit_internal typ {env with cur_inhabiting= TypSet.add typ env.cur_inhabiting} - in - ( inhabited_exp - , {env' with cache= TypMap.add typ inhabited_exp env.cache; cur_inhabiting= env.cur_inhabiting} - ) - - -(** inhabit each of the types in the formals list *) -and inhabit_args tenv formals cfg env = - let inhabit_arg (_, formal_typ) (args, env) = - let exp, env = inhabit_typ tenv formal_typ cfg env in - ((exp, formal_typ) :: args, env) - in - List.fold_right ~f:inhabit_arg formals ~init:([], env) - - -(** create Sil that calls the constructor in constr_name on allocated_obj and inhabits the - * remaining arguments *) -and inhabit_constructor tenv constr_name (allocated_obj, obj_type) cfg env = - try - (* this lookup can fail when we try to get the procdesc of a procedure from a different - * module. this could be solved with a whole - program class hierarchy analysis *) - let args, env = - let non_receiver_formals = tl_or_empty (formals_from_name cfg constr_name) in - inhabit_args tenv non_receiver_formals cfg env - in - let constr_instr = - let fun_exp = fun_exp_from_name constr_name in - Sil.Call (None, fun_exp, (allocated_obj, obj_type) :: args, env.pc, CallFlags.default) - in - env_add_instr constr_instr env - with Not_found -> env - - -let inhabit_call_with_args procname procdesc args env = - let retval = - let ret_typ = Procdesc.get_ret_type procdesc in - let is_void = Typ.equal_desc ret_typ.Typ.desc Typ.Tvoid in - if is_void then None else Some (Ident.create_fresh Ident.knormal, ret_typ) - in - let call_instr = - let fun_exp = fun_exp_from_name procname in - let flags = - {CallFlags.default with CallFlags.cf_virtual= not (Typ.Procname.java_is_static procname)} - in - Sil.Call (retval, fun_exp, args, env.pc, flags) - in - env_add_instr call_instr env - - -(** create Sil that inhabits args to and calls proc_name *) -let inhabit_call tenv (procname, receiver) cfg env = - try - match procdesc_from_name cfg procname with - | Some procdesc -> - (* swap the type of the 'this' formal with the receiver type, if there is one *) - let formals = - match (Procdesc.get_formals procdesc, receiver) with - | (name, _) :: formals, Some receiver -> - (name, receiver) :: formals - | formals, None -> - formals - | [], Some _ -> - L.(die InternalError) - "Expected at least one formal to bind receiver to in method %a" Typ.Procname.pp - procname - in - let args, env = inhabit_args tenv formals cfg env in - inhabit_call_with_args procname procdesc args env - | None -> - env - with Not_found -> env - - -(** create a dummy file for the harness and associate them in the exe_env *) -let create_dummy_harness_filename harness_name = - let dummy_file_dir = Filename.temp_dir_name in - let file_str = - Typ.Procname.java_get_class_name harness_name ^ "_" ^ Typ.Procname.java_get_method harness_name - ^ ".java" - in - Filename.concat dummy_file_dir file_str - - -(* TODO (t3040429): fill this file up with Java-like code that matches the SIL *) - -(** write the SIL for the harness to a file *) -let write_harness_to_file harness_instrs harness_file_name = - let harness_file = Utils.create_outfile harness_file_name in - let pp_harness fmt = - List.iter - ~f:(fun instr -> Format.fprintf fmt "%a@\n" (Sil.pp_instr Pp.text) instr) - harness_instrs - in - Utils.do_outf harness_file (fun outf -> pp_harness outf.fmt ; Utils.close_outf outf) - - -(** add the harness proc to the cg and make sure its callees can be looked up by sym execution *) -let add_harness_to_cg harness_name harness_node cg = - Cg.add_defined_node cg (Typ.Procname.Java harness_name) ; - List.iter - ~f:(fun p -> Cg.add_edge cg (Typ.Procname.Java harness_name) p) - (Procdesc.Node.get_callees harness_node) - - -(** create and fill the appropriate nodes and add them to the harness cfg. also add the harness - * proc to the cg *) -let setup_harness_cfg harness_name env cg cfg = - (* each procedure has different scope: start names from id 0 *) - Ident.NameGenerator.reset () ; - let procname = Typ.Procname.Java harness_name in - let proc_attributes = - { (ProcAttributes.default procname Config.Java) with - ProcAttributes.is_defined= true; loc= env.pc } - in - let procdesc = Cfg.create_proc_desc cfg proc_attributes in - let harness_node = - (* important to reverse the list or there will be scoping issues! *) - let instrs = List.rev env.instrs in - let nodekind = Procdesc.Node.Stmt_node "method_body" in - Procdesc.create_node procdesc env.pc nodekind instrs - in - let start_node, exit_node = - let create_node kind = Procdesc.create_node procdesc env.pc kind [] in - let start_kind = Procdesc.Node.Start_node procname in - let exit_kind = Procdesc.Node.Exit_node procname in - (create_node start_kind, create_node exit_kind) - in - Procdesc.set_start_node procdesc start_node ; - Procdesc.set_exit_node procdesc exit_node ; - Procdesc.Node.add_locals_ret_declaration start_node proc_attributes [] ; - Procdesc.node_set_succs_exn procdesc start_node [harness_node] [exit_node] ; - Procdesc.node_set_succs_exn procdesc harness_node [exit_node] [exit_node] ; - add_harness_to_cg harness_name harness_node cg - - -(** create a procedure named harness_name that calls each of the methods in trace in the specified - * order with the specified receiver and add it to the execution environment *) -let inhabit_trace tenv trace harness_name cg cfg = - if List.length trace > 0 then - let source_file = Cg.get_source cg in - let harness_filename = create_dummy_harness_filename harness_name in - let start_line = 1 in - let empty_env = - let pc = {Location.line= start_line; col= 1; file= source_file} in - {instrs= []; cache= TypMap.empty; pc; cur_inhabiting= TypSet.empty; harness_name} - in - (* invoke lifecycle methods *) - let env'' = - List.fold ~f:(fun env to_call -> inhabit_call tenv to_call cfg env) ~init:empty_env trace - in - try - setup_harness_cfg harness_name env'' cg cfg ; - write_harness_to_file (List.rev env''.instrs) harness_filename - with Not_found -> () - diff --git a/infer/src/harness/inhabit.mli b/infer/src/harness/inhabit.mli deleted file mode 100644 index dab2b8c04..000000000 --- a/infer/src/harness/inhabit.mli +++ /dev/null @@ -1,18 +0,0 @@ -(* - * Copyright (c) 2013 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - *) - -open! IStd - -(** Generate a procedure that calls a given sequence of methods. Useful for harness/test generation. *) - -type lifecycle_trace = (Typ.Procname.t * Typ.t option) list - -val inhabit_trace : Tenv.t -> lifecycle_trace -> Typ.Procname.java -> Cg.t -> Cfg.t -> unit -(** create a procedure named harness_name that calls each of the methods in trace add it to the - cg/cfg *) diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index 6b5087f04..f15d5b7f8 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -28,11 +28,10 @@ let init_global_state source_file = JContext.reset_exn_node_table () -let store_icfg source_file tenv cg cfg = +let store_icfg source_file cg cfg = let source_dir = DB.source_dir_from_source_file source_file in let cfg_file = DB.source_dir_get_internal_file source_dir ".cfg" in let cg_file = DB.source_dir_get_internal_file source_dir ".cg" in - if Config.create_harness then Harness.create_harness cfg cg tenv ; Cg.store_to_file cg_file cg ; Cfg.store_to_file ~source_file cfg_file cfg ; if Config.debug_mode || Config.frontend_tests then ( @@ -50,7 +49,7 @@ let do_source_file linereader classes program tenv source_basename package_opt s JFrontend.compute_source_icfg linereader classes program tenv source_basename package_opt source_file in - store_icfg source_file tenv call_graph cfg + store_icfg source_file call_graph cfg let capture_libs linereader program tenv = @@ -66,7 +65,7 @@ let capture_libs linereader program tenv = let call_graph, cfg = JFrontend.compute_class_icfg fake_source_file linereader program tenv node in - store_icfg fake_source_file tenv call_graph cfg ; + store_icfg fake_source_file call_graph cfg ; JFrontend.cache_classname cn in JBasics.ClassMap.iter (capture_class tenv) (JClasspath.get_classmap program) diff --git a/infer/src/jbuild.in b/infer/src/jbuild.in index a15e85c1a..c71721bda 100644 --- a/infer/src/jbuild.in +++ b/infer/src/jbuild.in @@ -15,7 +15,6 @@ let source_dirs = ; "checkers" ; "concurrency" ; "eradicate" - ; "harness" ; "integration" ; "IR" ; "labs" diff --git a/infer/tests/codetoanalyze/java/harness/BasicHarnessActivity.java b/infer/tests/codetoanalyze/java/harness/BasicHarnessActivity.java deleted file mode 100644 index e198b3c6b..000000000 --- a/infer/tests/codetoanalyze/java/harness/BasicHarnessActivity.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2015 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -package codetoanalyze.java.harness; - -import android.app.Activity; -import android.os.Bundle; - -/* - * Test if harness generation understands basics of Activity lifecycle. - */ -public class BasicHarnessActivity extends Activity { - - public BasicHarnessActivity(BasicHarnessActivity a) { - } - - private Object mObj; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mObj = new Object(); - } - - @Override - public void onPause() { - mObj = null; - } - - @Override - public void onDestroy() { - String s = mObj.toString(); - } - -} diff --git a/infer/tests/codetoanalyze/java/harness/Makefile b/infer/tests/codetoanalyze/java/harness/Makefile deleted file mode 100644 index 5f35de25e..000000000 --- a/infer/tests/codetoanalyze/java/harness/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2016 - present Facebook, Inc. -# All rights reserved. -# -# This source code is licensed under the BSD style license found in the -# LICENSE file in the root directory of this source tree. An additional grant -# of patent rights can be found in the PATENTS file in the same directory. - -TESTS_DIR = ../../.. - -ANALYZER = checkers -INFER_OPTIONS = --biabduction-only --android-harness --no-filtering --debug-exceptions -INFERPRINT_OPTIONS = --issues-fields "file,procedure,line_offset,bug_type" --issues-tests -SOURCES = \ - BasicHarnessActivity.java \ - -include $(TESTS_DIR)/javac.make diff --git a/infer/tests/codetoanalyze/java/harness/MyView.java b/infer/tests/codetoanalyze/java/harness/MyView.java deleted file mode 100644 index 69e0d4045..000000000 --- a/infer/tests/codetoanalyze/java/harness/MyView.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2015 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -package codetoanalyze.java.harness; - -import android.content.Context; -import android.view.View; - -public class MyView extends View { - public MyView(Context ctx) { - super(ctx); - } -} diff --git a/infer/tests/codetoanalyze/java/harness/TrickyParamsActivity.java b/infer/tests/codetoanalyze/java/harness/TrickyParamsActivity.java deleted file mode 100644 index e25869f7a..000000000 --- a/infer/tests/codetoanalyze/java/harness/TrickyParamsActivity.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2015 - present Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -package codetoanalyze.java.harness; - -import android.app.Activity; - -/* - * Test if type inhabitation can inhabit tricky types. - */ -public class TrickyParamsActivity extends Activity { - - private Object mObj; - - // we have to be able to inhabit all params or no methods from this - // class will be called by the harness - public TrickyParamsActivity( - Object o, int i, boolean b, char c, long l, - float f, double d, short sh, byte byt, - Object[] arr1, int[] arr2) { - this.mObj = new Object(); - } - - @Override - public void onPause() { - mObj = null; - } - - @Override - public void onDestroy() { - String s = mObj.toString(); - } - -} diff --git a/infer/tests/codetoanalyze/java/harness/issues.exp b/infer/tests/codetoanalyze/java/harness/issues.exp deleted file mode 100644 index 9e14a8680..000000000 --- a/infer/tests/codetoanalyze/java/harness/issues.exp +++ /dev/null @@ -1 +0,0 @@ -codetoanalyze/java/harness/BasicHarnessActivity.java, BasicHarnessActivity.InferGeneratedHarness(), -1, NULL_DEREFERENCE