[classloads] fix treatment of static initializers

Reviewed By: jvillard

Differential Revision: D13751141

fbshipit-source-id: f64af292b
master
Nikos Gorogiannis 6 years ago committed by Facebook Github Bot
parent 00df708f98
commit 5686d67072

@ -603,6 +603,8 @@ module Procname = struct
type java_type = Name.Java.Split.t = {package: string option; type_name: string}
[@@deriving compare]
let java_void = {package= None; type_name= "void"}
(** Type of java procedure names. *)
type t =
{ method_name: string
@ -741,6 +743,14 @@ module Procname = struct
let is_class_initializer {method_name} = String.equal method_name class_initializer_method_name
let get_class_initializer class_name =
{ method_name= class_initializer_method_name
; parameters= []
; class_name
; return_type= Some java_void
; kind= Static }
let is_anonymous_inner_class_constructor {class_name} =
Name.Java.is_anonymous_inner_class_name class_name

@ -391,6 +391,9 @@ module Procname : sig
val is_class_initializer : t -> bool
(** Check if this is a class initializer. *)
val get_class_initializer : Name.t -> t
(** Given a java class, generate the procname of its static initializer. *)
val is_external : t -> bool
(** Check if the method belongs to one of the specified external packages *)
end

@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module L = Logging
module F = Format
module Payload = SummaryPayload.Make (struct
type t = ClassLoadsDomain.summary
@ -53,18 +55,21 @@ let class_initializer_of_method pdesc =
| Java java_pname when Java.is_class_initializer java_pname ->
None
| Java java_pname ->
Some (Java Java.(replace_method_name class_initializer_method_name java_pname))
let class_name = Java.get_class_type_name java_pname in
Some (Java (Java.get_class_initializer class_name))
| _ ->
assert false
let analyze_procedure {Callbacks.proc_desc; summary} =
let proc_name = Procdesc.get_proc_name proc_desc in
L.debug Analysis Verbose "CL: ANALYZING %a@." Typ.Procname.pp proc_name ;
let loc = Procdesc.get_loc proc_desc in
(* add a load for the method's class *)
let init =
get_java_class proc_name
|> Option.fold ~init:ClassLoadsDomain.empty ~f:(ClassLoadsDomain.add_load loc)
let class_opt = get_java_class proc_name in
L.debug Analysis Verbose "CL: CLASS = %a@." (Pp.option F.pp_print_string) class_opt ;
Option.fold class_opt ~init:ClassLoadsDomain.empty ~f:(ClassLoadsDomain.add_load loc)
in
(* add loads done by the static initialization of this method's class *)
let after_class_init =
@ -75,4 +80,6 @@ let analyze_procedure {Callbacks.proc_desc; summary} =
in
let post = Procdesc.fold_instrs proc_desc ~init:after_class_init ~f:(exec_instr proc_desc) in
report_loads proc_desc summary post ;
Payload.update_summary post summary
let result = Payload.update_summary post summary in
L.debug Analysis Verbose "CL: FINISHED ANALYZING %a@." Typ.Procname.pp proc_name ;
result

@ -6,6 +6,7 @@
*)
open! IStd
module F = Format
module L = Logging
module ClassLoad = struct
include String
@ -28,11 +29,13 @@ let add ({Event.trace} as x) astate =
let union xs ys = fold add xs ys
let add_load loc astate clazz =
L.debug Analysis Verbose "CL: LOADING class %s@." clazz ;
let new_event = Event.make clazz loc in
add new_event astate
let integrate_summary callee_pname loc astate callee_summary =
L.debug Analysis Verbose "CL: ADDING SUMMARY OF %a@." Typ.Procname.pp callee_pname ;
let callsite = CallSite.make callee_pname loc in
let summary = with_callsite callee_summary callsite in
union astate summary

@ -15,7 +15,7 @@ SOURCES = $(wildcard *.java)
LOADS = $(patsubst %.java,%.loads,$(SOURCES))
OBJECTS = $(patsubst %.java,%.class,$(SOURCES))
CLASS_LOADS_OPT = $(patsubst %.java,--class-loads-roots %.main,$(SOURCES))
INFER_OPTIONS = -j 1 --class-loads-only $(CLASS_LOADS_OPT) --debug-exceptions
INFER_OPTIONS = --class-loads-only $(CLASS_LOADS_OPT) --debug-exceptions
CLEAN_EXTRA = *.class *.loads loads.exp loads.exp.test
include $(TESTS_DIR)/java.make

@ -0,0 +1,25 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class Static {
// this loads StaticA
static StaticA s = new StaticA();
public static void main(String args[]) {}
}
class StaticA {
// this loads StaticB
static StaticB b = new StaticB();
}
class StaticB {
// no load here
static StaticC c = null;
}
class StaticC {}
Loading…
Cancel
Save