Use Typename.t for the type of the supertypes in the defintion of classes.

Summary:
public
Using Typename.t in the list of superclasses to match the type for the key of the type environment. This avoids to make back and forth convertions from typename to type (csu, mangled name).

Depends on D2786574

Reviewed By: jberdine

Differential Revision: D2792116

fb-gh-sync-id: 6100f1a
master
jrm 9 years ago committed by facebook-github-bot-5
parent 6d91199be7
commit 9f5159241f

@ -55,7 +55,7 @@ exception Frontend_warning of string * Localise.error_desc * ml_location
exception Checkers of string * Localise.error_desc exception Checkers of string * Localise.error_desc
exception Inherently_dangerous_function of Localise.error_desc exception Inherently_dangerous_function of Localise.error_desc
exception Internal_error of Localise.error_desc exception Internal_error of Localise.error_desc
exception Java_runtime_exception of Mangled.t * string * Localise.error_desc exception Java_runtime_exception of Typename.t * string * Localise.error_desc
exception Leak of bool * Prop.normal Prop.t * Sil.hpred * (exception_visibility * Localise.error_desc) * bool * Sil.resource * ml_location exception Leak of bool * Prop.normal Prop.t * Sil.hpred * (exception_visibility * Localise.error_desc) * bool * Sil.resource * ml_location
exception Missing_fld of Ident.fieldname * ml_location exception Missing_fld of Ident.fieldname * ml_location
exception Premature_nil_termination of Localise.error_desc * ml_location exception Premature_nil_termination of Localise.error_desc * ml_location
@ -159,7 +159,7 @@ let recognize_exception exn =
let desc = Localise.verbatim_desc s in let desc = Localise.verbatim_desc s in
(Localise.from_string "Invalid_argument", desc, None, Exn_system, Low, None, Nocat) (Localise.from_string "Invalid_argument", desc, None, Exn_system, Low, None, Nocat)
| Java_runtime_exception (exn_name, pre_str, desc) -> | Java_runtime_exception (exn_name, pre_str, desc) ->
let exn_str = Mangled.to_string exn_name in let exn_str = Typename.name exn_name in
(Localise.from_string exn_str, desc, None, Exn_user, High, None, Prover) (Localise.from_string exn_str, desc, None, Exn_user, High, None, Prover)
| Leak (fp_part, _, _, (exn_vis, error_desc), done_array_abstraction, resource, mloc) -> | Leak (fp_part, _, _, (exn_vis, error_desc), done_array_abstraction, resource, mloc) ->
if done_array_abstraction if done_array_abstraction

@ -55,7 +55,7 @@ exception Checkers of string * Localise.error_desc
exception Frontend_warning of string * Localise.error_desc * ml_location exception Frontend_warning of string * Localise.error_desc * ml_location
exception Inherently_dangerous_function of Localise.error_desc exception Inherently_dangerous_function of Localise.error_desc
exception Internal_error of Localise.error_desc exception Internal_error of Localise.error_desc
exception Java_runtime_exception of Mangled.t * string * Localise.error_desc exception Java_runtime_exception of Typename.t * string * Localise.error_desc
exception Leak of bool * Prop.normal Prop.t * Sil.hpred * (exception_visibility * Localise.error_desc) * bool * Sil.resource * ml_location exception Leak of bool * Prop.normal Prop.t * Sil.hpred * (exception_visibility * Localise.error_desc) * bool * Sil.resource * ml_location
exception Missing_fld of Ident.fieldname * ml_location exception Missing_fld of Ident.fieldname * ml_location
exception Premature_nil_termination of Localise.error_desc * ml_location exception Premature_nil_termination of Localise.error_desc * ml_location

@ -361,7 +361,7 @@ let deref_str_uninitialized alloc_att_opt =
(** Java unchecked exceptions errors *) (** Java unchecked exceptions errors *)
let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc = let java_unchecked_exn_desc proc_name exn_name pre_str : error_desc =
([Procname.to_string proc_name; ([Procname.to_string proc_name;
"can throw "^(Mangled.to_string exn_name); "can throw "^(Typename.name exn_name);
"whenever "^pre_str], None, []) "whenever "^pre_str], None, [])
let desc_context_leak pname context_typ fieldname leak_path : error_desc = let desc_context_leak pname context_typ fieldname leak_path : error_desc =

@ -195,7 +195,7 @@ val desc_leak :
val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc val desc_null_test_after_dereference : string -> int -> Location.t -> error_desc
val java_unchecked_exn_desc : Procname.t -> Mangled.t -> string -> error_desc val java_unchecked_exn_desc : Procname.t -> Typename.t -> string -> error_desc
val desc_context_leak : val desc_context_leak :
Procname.t -> Sil.typ -> Ident.fieldname -> (Ident.fieldname option * Sil.typ) list -> error_desc Procname.t -> Sil.typ -> Ident.fieldname -> (Ident.fieldname option * Sil.typ) list -> error_desc

@ -47,7 +47,7 @@ module Path : sig
val equal : t -> t -> bool val equal : t -> t -> bool
(** extend a path with a new node reached from the given session, with an optional string for exceptions *) (** extend a path with a new node reached from the given session, with an optional string for exceptions *)
val extend : Cfg.node -> Mangled.t option -> session -> t -> t val extend : Cfg.node -> Typename.t option -> session -> t -> t
(** extend a path with a new node reached from the given session, with an optional string for exceptions *) (** extend a path with a new node reached from the given session, with an optional string for exceptions *)
val add_description : t -> string -> t val add_description : t -> string -> t
@ -60,7 +60,8 @@ module Path : sig
(** iterate over the longest sequence belonging to the path, restricting to those containing the given position if given. (** iterate over the longest sequence belonging to the path, restricting to those containing the given position if given.
Do not iterate past the given position. Do not iterate past the given position.
[f level path session exn_opt] is passed the current nesting [level] and [path] and previous [session] *) [f level path session exn_opt] is passed the current nesting [level] and [path] and previous [session] *)
val iter_longest_sequence : (int -> t -> int -> Mangled.t option -> unit) -> Sil.path_pos option -> t -> unit val iter_longest_sequence :
(int -> t -> int -> Typename.t option -> unit) -> Sil.path_pos option -> t -> unit
(** join two paths *) (** join two paths *)
val join : t -> t -> t val join : t -> t -> t
@ -83,7 +84,9 @@ end = struct
(* INVARIANT: stats are always set to dummy_stats unless we are in the middle of a traversal *) (* INVARIANT: stats are always set to dummy_stats unless we are in the middle of a traversal *)
(* in particular: a new traversal cannot be initiated during an existing traversal *) (* in particular: a new traversal cannot be initiated during an existing traversal *)
| Pstart of Cfg.node * stats (** start node *) | Pstart of Cfg.node * stats (** start node *)
| Pnode of Cfg.node * Mangled.t option * session * path * stats * string option (** we got to [node] from last [session] perhaps propagating exception [exn_opt], and continue with [path]. *) | Pnode of Cfg.node * Typename.t option * session * path * stats * string option
(** we got to [node] from last [session] perhaps propagating exception [exn_opt],
and continue with [path]. *)
| Pjoin of path * path * stats (** join of two paths *) | Pjoin of path * path * stats (** join of two paths *)
| Pcall of path * Procname.t * path * stats (** add a sub-path originating from a call *) | Pcall of path * Procname.t * path * stats (** add a sub-path originating from a call *)
@ -125,7 +128,7 @@ end = struct
| None, None -> 0 | None, None -> 0
| None, _ -> -1 | None, _ -> -1
| _, None -> 1 | _, None -> 1
| Some n1, Some n2 -> Mangled.compare n1 n2 | Some n1, Some n2 -> Typename.compare n1 n2
let rec compare p1 p2 : int = let rec compare p1 p2 : int =
if p1 == p2 then 0 else match p1, p2 with if p1 == p2 then 0 else match p1, p2 with
@ -281,7 +284,9 @@ end = struct
(** iterate over the longest sequence belonging to the path, restricting to those where [filter] holds of some element. (** iterate over the longest sequence belonging to the path, restricting to those where [filter] holds of some element.
if a node is reached via an exception, pass the exception information to [f] on the previous node *) if a node is reached via an exception, pass the exception information to [f] on the previous node *)
let iter_longest_sequence_filter (f : int -> t -> int -> Mangled.t option -> unit) (filter: Cfg.Node.t -> bool) (path: t) : unit = let iter_longest_sequence_filter
(f : int -> t -> int -> Typename.t option -> unit)
(filter: Cfg.Node.t -> bool) (path: t) : unit =
let rec doit level session path prev_exn_opt = match path with let rec doit level session path prev_exn_opt = match path with
| Pstart _ -> f level path session prev_exn_opt | Pstart _ -> f level path session prev_exn_opt
| Pnode (node, exn_opt, session', p, _, _) -> | Pnode (node, exn_opt, session', p, _, _) ->
@ -301,7 +306,9 @@ end = struct
(** iterate over the longest sequence belonging to the path, restricting to those containing the given position if given. (** iterate over the longest sequence belonging to the path, restricting to those containing the given position if given.
Do not iterate past the last occurrence of the given position. Do not iterate past the last occurrence of the given position.
[f level path session exn_opt] is passed the current nesting [level] and [path] and previous [session] and possible exception [exn_opt] *) [f level path session exn_opt] is passed the current nesting [level] and [path] and previous [session] and possible exception [exn_opt] *)
let iter_longest_sequence (f : int -> t -> int -> Mangled.t option -> unit) (pos_opt : Sil.path_pos option) (path: t) : unit = let iter_longest_sequence
(f : int -> t -> int -> Typename.t option -> unit)
(pos_opt : Sil.path_pos option) (path: t) : unit =
let filter node = match pos_opt with let filter node = match pos_opt with
| None -> true | None -> true
| Some pos -> Sil.path_pos_equal (get_path_pos node) pos in | Some pos -> Sil.path_pos_equal (get_path_pos node) pos in
@ -478,7 +485,7 @@ end = struct
match exn_opt with match exn_opt with
| None -> "", [] | None -> "", []
| Some exn_name -> | Some exn_name ->
let exn_str = Mangled.to_string exn_name in let exn_str = Typename.name exn_name in
if exn_str = "" if exn_str = ""
then "exception", [(Io_infer.Xml.tag_kind,"exception")] then "exception", [(Io_infer.Xml.tag_kind,"exception")]
else else

@ -40,7 +40,7 @@ module Path : sig
val d_stats : t -> unit val d_stats : t -> unit
(** extend a path with a new node reached from the given session, with an optional string for exceptions *) (** extend a path with a new node reached from the given session, with an optional string for exceptions *)
val extend : Cfg.node -> Mangled.t option -> session -> t -> t val extend : Cfg.node -> Typename.t option -> session -> t -> t
val add_description : t -> string -> t val add_description : t -> string -> t
@ -50,7 +50,8 @@ module Path : sig
(** iterate over the longest sequence belonging to the path, restricting to those containing the given position if given. (** iterate over the longest sequence belonging to the path, restricting to those containing the given position if given.
Do not iterate past the given position. Do not iterate past the given position.
[f level path session exn_opt] is passed the current nesting [level] and [path] and previous [session] and possible exception [exn_opt] *) [f level path session exn_opt] is passed the current nesting [level] and [path] and previous [session] and possible exception [exn_opt] *)
val iter_longest_sequence : (int -> t -> int -> Mangled.t option -> unit) -> Sil.path_pos option -> t -> unit val iter_longest_sequence :
(int -> t -> int -> Typename.t option -> unit) -> Sil.path_pos option -> t -> unit
(** join two paths *) (** join two paths *)
val join : t -> t -> t val join : t -> t -> t

@ -1440,27 +1440,27 @@ let expand_hpred_pointer calc_index_frame hpred : bool * bool * Sil.hpred =
| _ -> changed, calc_index_frame, hpred in | _ -> changed, calc_index_frame, hpred in
expand false calc_index_frame hpred expand false calc_index_frame hpred
let object_type = Mangled.from_string "java.lang.Object" let object_type = Typename.Java.from_string "java.lang.Object"
let serializable_type = Mangled.from_string "java.io.Serializable" let serializable_type = Typename.Java.from_string "java.io.Serializable"
let cloneable_type = Mangled.from_string "java.lang.Cloneable" let cloneable_type = Typename.Java.from_string "java.lang.Cloneable"
let is_interface tenv c = let is_interface tenv class_name =
match Sil.tenv_lookup tenv (Typename.TN_csu (Csu.Class, c)) with match Sil.tenv_lookup tenv class_name with
| Some (Sil.Tstruct (fields, sfields, Csu.Class, Some c1', supers1, methods, iann)) -> | Some (Sil.Tstruct (fields, sfields, Csu.Class, Some c1', supers1, methods, iann)) ->
(IList.length fields = 0) && (IList.length methods = 0) (IList.length fields = 0) && (IList.length methods = 0)
| _ -> false | _ -> false
(** check if c1 is a subclass of c2 *) (** check if c1 is a subclass of c2 *)
let check_subclass_tenv tenv c1 c2 = let check_subclass_tenv tenv c1 c2 =
let rec check (_, c) = let rec check cn =
Mangled.equal c c2 || (Mangled.equal c2 object_type) || Typename.equal cn c2 || Typename.equal c2 object_type ||
match Sil.tenv_lookup tenv (Typename.TN_csu (Csu.Class, c)) with match Sil.tenv_lookup tenv cn with
| Some (Sil.Tstruct (_, _, Csu.Class, Some c1', supers1, _, _)) -> | Some (Sil.Tstruct (_, _, Csu.Class, Some c1', supers1, _, _)) ->
IList.exists check supers1 IList.exists check supers1
| _ -> false in | _ -> false in
(check (Csu.Class, c1)) check c1
let check_subclass tenv c1 c2 = let check_subclass tenv c1 c2 =
let f = check_subclass_tenv tenv in let f = check_subclass_tenv tenv in
@ -1480,7 +1480,9 @@ let rec check_subtype tenv t1 t2 =
match t1, t2 with match t1, t2 with
| Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), | Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _),
Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) -> Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) ->
(check_subclass tenv c1 c2) let cn1 = Typename.TN_csu (Csu.Class, c1)
and cn2 = Typename.TN_csu (Csu.Class, c2) in
(check_subclass tenv cn1 cn2)
| Sil.Tarray (dom_type1, _), Sil.Tarray (dom_type2, _) -> | Sil.Tarray (dom_type1, _), Sil.Tarray (dom_type2, _) ->
check_subtype tenv dom_type1 dom_type2 check_subtype tenv dom_type1 dom_type2
@ -1489,7 +1491,10 @@ let rec check_subtype tenv t1 t2 =
check_subtype tenv dom_type1 dom_type2 check_subtype tenv dom_type1 dom_type2
| Sil.Tarray _, Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) -> | Sil.Tarray _, Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) ->
(Mangled.equal c2 serializable_type) || (Mangled.equal c2 cloneable_type) || (Mangled.equal c2 object_type) let cn2 = Typename.TN_csu (Csu.Class, c2) in
Typename.equal cn2 serializable_type
|| Typename.equal cn2 cloneable_type
|| Typename.equal cn2 object_type
| _ -> (check_subtype_basic_type t1 t2) | _ -> (check_subtype_basic_type t1 t2)
@ -1497,7 +1502,9 @@ let rec case_analysis_type tenv (t1, st1) (t2, st2) =
match t1, t2 with match t1, t2 with
| Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), | Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _),
Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) -> Sil.Tstruct (_, _, Csu.Class, Some c2, _, _, _) ->
(Sil.Subtype.case_analysis (c1, st1) (c2, st2) (check_subclass tenv) (is_interface tenv)) let cn1 = Typename.TN_csu (Csu.Class, c1)
and cn2 = Typename.TN_csu (Csu.Class, c2) in
(Sil.Subtype.case_analysis (cn1, st1) (cn2, st2) (check_subclass tenv) (is_interface tenv))
| Sil.Tarray (dom_type1, _), Sil.Tarray (dom_type2, _) -> | Sil.Tarray (dom_type1, _), Sil.Tarray (dom_type2, _) ->
(case_analysis_type tenv (dom_type1, st1) (dom_type2, st2)) (case_analysis_type tenv (dom_type1, st1) (dom_type2, st2))
@ -1506,7 +1513,10 @@ let rec case_analysis_type tenv (t1, st1) (t2, st2) =
(case_analysis_type tenv (dom_type1, st1) (dom_type2, st2)) (case_analysis_type tenv (dom_type1, st1) (dom_type2, st2))
| Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), Sil.Tarray _ -> | Sil.Tstruct (_, _, Csu.Class, Some c1, _, _, _), Sil.Tarray _ ->
if ((Mangled.equal c1 serializable_type) || (Mangled.equal c1 cloneable_type) || (Mangled.equal c1 object_type)) && let cn1 = Typename.TN_csu (Csu.Class, c1) in
if (Typename.equal cn1 serializable_type
|| Typename.equal cn1 cloneable_type
|| Typename.equal cn1 object_type) &&
(st1 <> Sil.Subtype.exact) then (Some st1, None) (st1 <> Sil.Subtype.exact) then (Some st1, None)
else (None, Some st1) else (None, Some st1)

@ -202,14 +202,15 @@ module Subtype = struct
| [] -> "" | [] -> ""
| el:: rest -> | el:: rest ->
let s = (aux rest) in let s = (aux rest) in
if (s = "") then (Mangled.to_string el) if (s = "") then (Typename.name el)
else (Mangled.to_string el)^", "^s in else (Typename.name el)^", "^s in
if (IList.length list = 0) then "( sub )" if (IList.length list = 0) then "( sub )"
else ("- {"^(aux list)^"}") else ("- {"^(aux list)^"}")
type t' = type t' =
| Exact (** denotes the current type only *) | Exact (** denotes the current type only *)
| Subtypes of Mangled.t list(** denotes the current type and a list of types that are not their subtypes *) | Subtypes of Typename.t list
(** denotes the current type and a list of types that are not their subtypes *)
type kind = type kind =
| CAST | CAST
@ -219,10 +220,10 @@ module Subtype = struct
type t = t' * kind type t = t' * kind
module SubtypesPair = struct module SubtypesPair = struct
type t = (Mangled.t * Mangled.t) type t = (Typename.t * Typename.t)
let compare (e1 : t)(e2 : t) : int = let compare (e1 : t)(e2 : t) : int =
pair_compare Mangled.compare Mangled.compare e1 e2 pair_compare Typename.compare Typename.compare e1 e2
end end
module SubtypesMap = Map.Make (SubtypesPair) module SubtypesMap = Map.Make (SubtypesPair)
@ -246,9 +247,12 @@ module Subtype = struct
| NORMAL -> "" | NORMAL -> ""
let pp f (t, flag) = let pp f (t, flag) =
match t with if !Config.print_types then
| Exact -> if !Config.print_types then F.fprintf f "%s" (flag_to_string flag) match t with
| Subtypes list -> if !Config.print_types then F.fprintf f "%s" ((list_to_string list)^(flag_to_string flag)) | Exact ->
F.fprintf f "%s" (flag_to_string flag)
| Subtypes list ->
F.fprintf f "%s" ((list_to_string list)^(flag_to_string flag))
let exact = Exact, NORMAL let exact = Exact, NORMAL
let all_subtypes = Subtypes [] let all_subtypes = Subtypes []
@ -275,12 +279,12 @@ module Subtype = struct
match s1, s2 with match s1, s2 with
| Exact, _ -> s2 | Exact, _ -> s2
| _, Exact -> s1 | _, Exact -> s1
| Subtypes l1, Subtypes l2 -> Subtypes (list_intersect Mangled.equal l1 l2) in | Subtypes l1, Subtypes l2 -> Subtypes (list_intersect Typename.equal l1 l2) in
let flag = join_flag flag1 flag2 in let flag = join_flag flag1 flag2 in
s, flag s, flag
let subtypes_compare l1 l2 = let subtypes_compare l1 l2 =
IList.compare Mangled.compare l1 l2 IList.compare Typename.compare l1 l2
let compare_flag flag1 flag2 = let compare_flag flag1 flag2 =
match flag1, flag2 with match flag1, flag2 with
@ -309,7 +313,7 @@ module Subtype = struct
let update_flag c1 c2 flag flag' = let update_flag c1 c2 flag flag' =
match flag with match flag with
| INSTOF -> | INSTOF ->
if (Mangled.equal c1 c2) then flag else flag' if (Typename.equal c1 c2) then flag else flag'
| _ -> flag' | _ -> flag'
let change_flag st_opt c1 c2 flag' = let change_flag st_opt c1 c2 flag' =
@ -331,7 +335,7 @@ module Subtype = struct
(match t with (match t with
| Exact -> Some (t, new_flag) | Exact -> Some (t, new_flag)
| Subtypes l -> | Subtypes l ->
Some (Subtypes (IList.sort Mangled.compare l), new_flag)) Some (Subtypes (IList.sort Typename.compare l), new_flag))
| None -> None | None -> None
let subtypes_to_string t = let subtypes_to_string t =
@ -345,7 +349,7 @@ module Subtype = struct
with Not_found -> true with Not_found -> true
let is_strict_subtype f c1 c2 = let is_strict_subtype f c1 c2 =
f c1 c2 && not (Mangled.equal c1 c2) f c1 c2 && not (Typename.equal c1 c2)
(* checks for redundancies when adding c to l (* checks for redundancies when adding c to l
Xi in A - { X1,..., Xn } is redundant in two cases: Xi in A - { X1,..., Xn } is redundant in two cases:
@ -381,8 +385,6 @@ module Subtype = struct
let get_subtypes (c1, (st1, flag1)) (c2, (st2, flag2)) f is_interface = let get_subtypes (c1, (st1, flag1)) (c2, (st2, flag2)) f is_interface =
let is_sub = f c1 c2 in let is_sub = f c1 c2 in
(* L.d_strln_color Orange ((Mangled.to_string c1)^(subtypes_to_string (st1, flag1))^" <: "^ *)
(* (Mangled.to_string c2)^(subtypes_to_string (st2, flag2))^" ?"^(string_of_bool is_sub)); *)
let pos_st, neg_st = match st1, st2 with let pos_st, neg_st = match st1, st2 with
| Exact, Exact -> | Exact, Exact ->
if (is_sub) then (Some st1, None) if (is_sub) then (Some st1, None)
@ -414,11 +416,11 @@ module Subtype = struct
else if f c2 c1 then else if f c2 c1 then
match st with match st with
| Exact, flag -> | Exact, flag ->
if Mangled.equal c1 c2 if Typename.equal c1 c2
then (Some st, None) then (Some st, None)
else (None, Some st) else (None, Some st)
| Subtypes _ , flag -> | Subtypes _ , flag ->
if Mangled.equal c1 c2 if Typename.equal c1 c2
then (Some st, None) then (Some st, None)
else (Some st, Some st) else (Some st, Some st)
else (None, Some st) in else (None, Some st) in
@ -651,7 +653,7 @@ and typ =
| Tfun of bool (** function type with noreturn attribute *) | Tfun of bool (** function type with noreturn attribute *)
| Tptr of typ * ptr_kind (** pointer type *) | Tptr of typ * ptr_kind (** pointer type *)
| Tstruct of struct_fields * struct_fields * Csu.t * Mangled.t option * | Tstruct of struct_fields * struct_fields * Csu.t * Mangled.t option *
(Csu.t * Mangled.t) list * Procname.t list * item_annotation Typename.t list * Procname.t list * item_annotation
(** Structure type with nonstatic and static fields, class/struct/union flag, name, (** Structure type with nonstatic and static fields, class/struct/union flag, name,
list of superclasses, methods defined, and annotations. list of superclasses, methods defined, and annotations.
The fld - typ pairs are always sorted. This means that we don't support programs that exploit specific layouts The fld - typ pairs are always sorted. This means that we don't support programs that exploit specific layouts

@ -140,13 +140,15 @@ module Subtype : sig
val subtypes_cast : t val subtypes_cast : t
val subtypes_instof : t val subtypes_instof : t
val join : t -> t -> t val join : t -> t -> t
(** [case_analysis (c1, st1) (c2,st2) f] performs case analysis on [c1 <: c2] according to [st1] and [st2] (** [case_analysis (c1, st1) (c2,st2) f] performs case analysis on [c1 <: c2] according
where f c1 c2 is true if c1 is a subtype of c2. to [st1] and [st2] where f c1 c2 is true if c1 is a subtype of c2.
get_subtypes returning a pair: get_subtypes returning a pair:
- whether [st1] and [st2] admit [c1 <: c2], and in case return the updated subtype [st1] - whether [st1] and [st2] admit [c1 <: c2], and in case return the updated subtype [st1]
- whether [st1] and [st2] admit [not(c1 <: c2)], and in case return the updated subtype [st1] *) - whether [st1] and [st2] admit [not(c1 <: c2)], and in case return
val case_analysis : (Mangled.t * t) -> (Mangled.t * t) -> (Mangled.t -> Mangled.t -> bool) -> (Mangled.t -> bool) -> t option * t option the updated subtype [st1] *)
val check_subtype : (Mangled.t -> Mangled.t -> bool) -> Mangled.t -> Mangled.t -> bool val case_analysis : (Typename.t * t) -> (Typename.t * t) ->
(Typename.t -> Typename.t -> bool) -> (Typename.t -> bool) -> t option * t option
val check_subtype : (Typename.t -> Typename.t -> bool) -> Typename.t -> Typename.t -> bool
val subtypes_to_string : t -> string val subtypes_to_string : t -> string
val is_cast : t -> bool val is_cast : t -> bool
val is_instof : t -> bool val is_instof : t -> bool
@ -286,7 +288,7 @@ and typ =
| Tfun of bool (** function type with noreturn attribute *) | Tfun of bool (** function type with noreturn attribute *)
| Tptr of typ * ptr_kind (** pointer type *) | Tptr of typ * ptr_kind (** pointer type *)
| Tstruct of struct_fields * struct_fields * Csu.t * Mangled.t option * | Tstruct of struct_fields * struct_fields * Csu.t * Mangled.t option *
(Csu.t * Mangled.t) list * Procname.t list * item_annotation Typename.t list * Procname.t list * item_annotation
(** Structure type with nonstatic and static fields, class/struct/union flag, name, list of superclasses, (** Structure type with nonstatic and static fields, class/struct/union flag, name, list of superclasses,
methods defined, and annotations. methods defined, and annotations.
The fld - typ pairs are always sorted. This means that we don't support programs that exploit specific layouts The fld - typ pairs are always sorted. This means that we don't support programs that exploit specific layouts

@ -598,23 +598,22 @@ let method_exists right_proc_name methods =
let resolve_method tenv class_name proc_name = let resolve_method tenv class_name proc_name =
let found_class = let found_class =
let visited = ref Mangled.MangledSet.empty in let visited = ref Typename.Set.empty in
let rec resolve class_name = let rec resolve class_name =
visited := Mangled.MangledSet.add class_name !visited; visited := Typename.Set.add class_name !visited;
let right_proc_name = let right_proc_name =
if Procname.is_java proc_name then if Procname.is_java proc_name then
Procname.java_replace_class proc_name (Mangled.to_string class_name) Procname.java_replace_class proc_name (Typename.name class_name)
else Procname.c_method_replace_class proc_name (Mangled.to_string class_name) in else Procname.c_method_replace_class proc_name (Typename.name class_name) in
let type_name = Typename.TN_csu (Csu.Class, class_name) in match Sil.tenv_lookup tenv class_name with
match Sil.tenv_lookup tenv type_name with
| Some (Sil.Tstruct (_, _, Csu.Class, cls, super_classes, methods, iann)) -> | Some (Sil.Tstruct (_, _, Csu.Class, cls, super_classes, methods, iann)) ->
if method_exists right_proc_name methods then if method_exists right_proc_name methods then
Some right_proc_name Some right_proc_name
else else
(match super_classes with (match super_classes with
| (Csu.Class, super_class):: interfaces -> | super_classname:: interfaces ->
if not (Mangled.MangledSet.mem super_class !visited) if not (Typename.Set.mem super_classname !visited)
then resolve super_class then resolve super_classname
else None else None
| _ -> None) | _ -> None)
| _ -> None in | _ -> None in
@ -622,7 +621,7 @@ let resolve_method tenv class_name proc_name =
match found_class with match found_class with
| None -> | None ->
Logging.d_strln Logging.d_strln
("Couldn't find method in the hierarchy of type "^(Mangled.to_string class_name)); ("Couldn't find method in the hierarchy of type "^(Typename.name class_name));
proc_name proc_name
| Some proc_name -> proc_name | Some proc_name -> proc_name
@ -635,8 +634,9 @@ let resolve_typename prop arg =
| _ :: hpreds -> loop hpreds in | _ :: hpreds -> loop hpreds in
loop (Prop.get_sigma prop) in loop (Prop.get_sigma prop) in
match typexp_opt with match typexp_opt with
| Some (Sil.Sizeof (Sil.Tstruct (_, _, Csu.Class, class_name_opt, _, _, _), _)) -> | Some (Sil.Sizeof (Sil.Tstruct (_, _, _, None, _, _, _), _)) -> None
class_name_opt | Some (Sil.Sizeof (Sil.Tstruct (_, _, Csu.Class, Some name, _, _, _), _)) ->
Some (Typename.TN_csu (Csu.Class, name))
| _ -> None | _ -> None
(** If the dynamic type of the object calling a method is known, the method from the dynamic type (** If the dynamic type of the object calling a method is known, the method from the dynamic type
@ -648,7 +648,7 @@ let resolve_virtual_pname cfg tenv prop args pname : Procname.t =
begin begin
match resolve_typename prop obj_exp with match resolve_typename prop obj_exp with
| Some class_name -> resolve_method tenv class_name pname | Some class_name -> resolve_method tenv class_name pname
| _ -> pname | None -> pname
end end
(* let resolve_procname cfg tenv prop args pname : Procname.t = *) (* let resolve_procname cfg tenv prop args pname : Procname.t = *)

@ -24,7 +24,7 @@ val lifted_sym_exec : (exn -> unit) -> Cfg.cfg -> Sil.tenv -> Cfg.Procdesc.t ->
* the procname that the method name will actually resolve to at runtime. For example, if we have * the procname that the method name will actually resolve to at runtime. For example, if we have
* a procname like Foo.toString() and Foo does not override toString(), we must resolve the call to * a procname like Foo.toString() and Foo does not override toString(), we must resolve the call to
* toString(). We will end up with Super.toString() where Super is some superclass of Foo. *) * toString(). We will end up with Super.toString() where Super is some superclass of Foo. *)
val resolve_method : Sil.tenv -> Mangled.t -> Procname.t -> Procname.t val resolve_method : Sil.tenv -> Typename.t -> Procname.t -> Procname.t
(** {2 Functions for handling builtins } *) (** {2 Functions for handling builtins } *)
module ModelBuiltins : sig module ModelBuiltins : sig

@ -594,11 +594,12 @@ let prop_is_exn pname prop =
(** when prop is an exception, return the exception name *) (** when prop is an exception, return the exception name *)
let prop_get_exn_name pname prop = let prop_get_exn_name pname prop =
let ret_pvar = Sil.Lvar (Sil.get_ret_pvar pname) in let ret_pvar = Sil.Lvar (Sil.get_ret_pvar pname) in
let exn_name = ref (Mangled.from_string "") in let exn_name = ref (Typename.Java.from_string "") in
let find_exn_name e = let find_exn_name e =
let do_hpred = function let do_hpred = function
| Sil.Hpointsto (e1, _, Sil.Sizeof(Sil.Tstruct (_, _, _, Some name, _, _, _), _)) when Sil.exp_equal e1 e -> | Sil.Hpointsto (e1, _, Sil.Sizeof(Sil.Tstruct (_, _, _, Some name, _, _, _), _)) when Sil.exp_equal e1 e ->
exn_name := name let found_exn_name = Typename.TN_csu (Csu.Class, name) in
exn_name := found_exn_name
| _ -> () in | _ -> () in
IList.iter do_hpred (Prop.get_sigma prop) in IList.iter do_hpred (Prop.get_sigma prop) in
let find_ret () = let find_ret () =

@ -30,7 +30,7 @@ val raise_cast_exception :
val prop_is_exn : Procname.t -> 'a Prop.t -> bool val prop_is_exn : Procname.t -> 'a Prop.t -> bool
(** when prop is an exception, return the exception name *) (** when prop is an exception, return the exception name *)
val prop_get_exn_name : Procname.t -> 'a Prop.t -> Mangled.t val prop_get_exn_name : Procname.t -> 'a Prop.t -> Typename.t
(** search in prop contains an error state *) (** search in prop contains an error state *)
val lookup_custom_errors : 'a Prop.t -> string option val lookup_custom_errors : 'a Prop.t -> string option

@ -311,8 +311,8 @@ let initial_node = ref (Cfg.Node.dummy ())
let rec super tenv t = let rec super tenv t =
match t with match t with
| Sil.Tstruct (_, _, Csu.Class, Some c2, (Csu.Class, super):: rest, _, _) -> | Sil.Tstruct (_, _, Csu.Class, Some c2, class_name :: rest, _, _) ->
Sil.tenv_lookup tenv (Typename.TN_csu (Csu.Class, super)) Sil.tenv_lookup tenv class_name
| Sil.Tarray (dom_type, _) -> None | Sil.Tarray (dom_type, _) -> None
| Sil.Tptr (dom_type, p) -> | Sil.Tptr (dom_type, p) ->
let super_dom_type = super tenv dom_type in let super_dom_type = super tenv dom_type in

@ -7,6 +7,9 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
open Utils
module F = Format
(** Named types. *) (** Named types. *)
type t = type t =
| TN_typedef of Mangled.t | TN_typedef of Mangled.t
@ -19,6 +22,9 @@ let to_string = function
| TN_csu (csu, name) -> | TN_csu (csu, name) ->
Csu.name csu ^ " " ^ Mangled.to_string name Csu.name csu ^ " " ^ Mangled.to_string name
let pp f typename =
F.fprintf f "%s" (to_string typename)
let name = function let name = function
| TN_enum name | TN_enum name
| TN_typedef name | TN_typedef name
@ -37,3 +43,18 @@ let compare tn1 tn2 = match tn1, tn2 with
let equal tn1 tn2 = let equal tn1 tn2 =
compare tn1 tn2 = 0 compare tn1 tn2 = 0
module Java =
struct
let from_string class_name_str =
TN_csu (Csu.Class, Mangled.from_string class_name_str)
end
type typename_t = t
module Set = Set.Make(
struct
type t = typename_t
let compare = compare
end)

@ -16,6 +16,8 @@ type t =
(** convert the typename to a string *) (** convert the typename to a string *)
val to_string : t -> string val to_string : t -> string
val pp : Format.formatter -> t -> unit
(** name of the typename without qualifier *) (** name of the typename without qualifier *)
val name : t -> string val name : t -> string
@ -24,3 +26,12 @@ val compare : t -> t -> int
(** Equality for typenames *) (** Equality for typenames *)
val equal : t -> t -> bool val equal : t -> t -> bool
module Java : sig
(** Create a typename from a Java classname in the form "package.class" *)
val from_string : string -> t
end
module Set : Set.S with type elt = t

@ -197,7 +197,9 @@ let callback_check_write_to_parcel all_procs get_proc_desc idenv tenv proc_name
let is_write_to_parcel this_expr this_type = let is_write_to_parcel this_expr this_type =
let method_match () = Procname.java_get_method proc_name = "writeToParcel" in let method_match () = Procname.java_get_method proc_name = "writeToParcel" in
let expr_match () = Sil.exp_is_this this_expr in let expr_match () = Sil.exp_is_this this_expr in
let type_match () = PatternMatch.is_direct_subtype_of this_type "android.os.Parcelable" in let type_match () =
let class_name = Typename.TN_csu (Csu.Class, Mangled.from_string "android.os.Parcelable") in
PatternMatch.is_direct_subtype_of this_type class_name in
method_match () && expr_match () && type_match () in method_match () && expr_match () && type_match () in
let is_parcel_constructor proc_name = let is_parcel_constructor proc_name =

@ -28,7 +28,7 @@ let java_proc_name_with_class_method pn class_with_path method_name =
let is_direct_subtype_of this_type super_type_name = let is_direct_subtype_of this_type super_type_name =
match this_type with match this_type with
| Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) -> | Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) ->
IList.exists (fun (x, y) -> super_type_name = Mangled.to_string y) supertypes IList.exists (fun cn -> Typename.equal cn super_type_name) supertypes
| _ -> false | _ -> false
(** The type the method is invoked on *) (** The type the method is invoked on *)
@ -38,8 +38,7 @@ let get_this_type proc_attributes = match proc_attributes.ProcAttributes.formals
let type_get_direct_supertypes = function let type_get_direct_supertypes = function
| Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) | Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _)
| Sil.Tstruct (_, _, _, _, supertypes, _, _) -> | Sil.Tstruct (_, _, _, _, supertypes, _, _) -> supertypes
IList.map (fun (_, m) -> m) supertypes
| _ -> [] | _ -> []
let type_get_class_name t = match t with let type_get_class_name t = match t with
@ -59,13 +58,13 @@ let type_get_annotation
let type_has_class_name t name = let type_has_class_name t name =
type_get_class_name t = Some name type_get_class_name t = Some name
let type_has_direct_supertype (t : Sil.typ) (s : Mangled.t) = let type_has_direct_supertype (typ : Sil.typ) (class_name : Typename.t) =
IList.exists (fun c -> c = s) (type_get_direct_supertypes t) IList.exists (fun cn -> Typename.equal cn class_name) (type_get_direct_supertypes typ)
let type_has_supertype let type_has_supertype
(tenv: Sil.tenv) (tenv: Sil.tenv)
(typ: Sil.typ) (typ: Sil.typ)
(name: Mangled.t): bool = (class_name: Typename.t): bool =
let rec has_supertype typ visited = let rec has_supertype typ visited =
if Sil.TypSet.mem typ visited then if Sil.TypSet.mem typ visited then
false false
@ -74,10 +73,10 @@ let type_has_supertype
match Sil.expand_type tenv typ with match Sil.expand_type tenv typ with
| Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _) | Sil.Tptr (Sil.Tstruct (_, _, _, _, supertypes, _, _), _)
| Sil.Tstruct (_, _, _, _, supertypes, _, _) -> | Sil.Tstruct (_, _, _, _, supertypes, _, _) ->
let match_supertype (csu, m) = let match_supertype cn =
let match_name () = Mangled.equal m name in let match_name () = Typename.equal cn class_name in
let has_indirect_supertype () = let has_indirect_supertype () =
match Sil.tenv_lookup tenv (Typename.TN_csu (Csu.Class, m)) with match Sil.tenv_lookup tenv cn with
| Some supertype -> has_supertype supertype (Sil.TypSet.add typ visited) | Some supertype -> has_supertype supertype (Sil.TypSet.add typ visited)
| None -> false in | None -> false in
(match_name () || has_indirect_supertype ()) in (match_name () || has_indirect_supertype ()) in
@ -93,7 +92,7 @@ let type_is_nested_in_type t n = match t with
| _ -> false | _ -> false
let type_is_nested_in_direct_supertype t n = let type_is_nested_in_direct_supertype t n =
let is_nested_in m2 m1 = string_is_prefix (Mangled.to_string m2 ^ "$") (Mangled.to_string m1) in let is_nested_in cn1 cn2 = string_is_prefix (Typename.name cn1 ^ "$") (Typename.name cn2) in
IList.exists (is_nested_in n) (type_get_direct_supertypes t) IList.exists (is_nested_in n) (type_get_direct_supertypes t)
let rec get_type_name = function let rec get_type_name = function
@ -224,12 +223,15 @@ let type_is_class = function
| Sil.Tstruct _ -> true | Sil.Tstruct _ -> true
| _ -> false | _ -> false
let initializer_classes = IList.map Mangled.from_string [ let initializer_classes =
"android.app.Activity"; IList.map
"android.app.Application"; (fun name -> Typename.TN_csu (Csu.Class, Mangled.from_string name))
"android.app.Fragment"; [
"android.support.v4.app.Fragment"; "android.app.Activity";
] "android.app.Application";
"android.app.Fragment";
"android.support.v4.app.Fragment";
]
let initializer_methods = [ let initializer_methods = [
"onActivityCreated"; "onActivityCreated";
@ -242,7 +244,7 @@ let initializer_methods = [
let type_has_initializer let type_has_initializer
(tenv: Sil.tenv) (tenv: Sil.tenv)
(t: Sil.typ): bool = (t: Sil.typ): bool =
let check_candidate cname = type_has_supertype tenv t cname in let check_candidate class_name = type_has_supertype tenv t class_name in
IList.exists check_candidate initializer_classes IList.exists check_candidate initializer_classes
(** Check if the method is one of the known initializer methods. *) (** Check if the method is one of the known initializer methods. *)
@ -300,9 +302,8 @@ let proc_calls resolve_attributes pname pdesc filter : (Procname.t * ProcAttribu
let proc_iter_overridden_methods f tenv proc_name = let proc_iter_overridden_methods f tenv proc_name =
let do_super_type tenv super_class_name = let do_super_type tenv super_class_name =
let super_proc_name = let super_proc_name =
Procname.java_replace_class proc_name (Mangled.to_string super_class_name) in Procname.java_replace_class proc_name (Typename.name super_class_name) in
let type_name = Typename.TN_csu (Csu.Class, super_class_name) in match Sil.tenv_lookup tenv super_class_name with
match Sil.tenv_lookup tenv type_name with
| Some (Sil.Tstruct (_, _, _, _, _, methods, _)) -> | Some (Sil.Tstruct (_, _, _, _, _, methods, _)) ->
let is_override pname = let is_override pname =
Procname.equal pname super_proc_name && Procname.equal pname super_proc_name &&

@ -38,7 +38,7 @@ val is_getter : Procname.t -> bool
val is_setter : Procname.t -> bool val is_setter : Procname.t -> bool
(** Is the type a direct subtype of *) (** Is the type a direct subtype of *)
val is_direct_subtype_of : Sil.typ -> string -> bool val is_direct_subtype_of : Sil.typ -> Typename.t -> bool
(** Get the name of the type of a constant *) (** Get the name of the type of a constant *)
val java_get_const_type_name : Sil.const -> string val java_get_const_type_name : Sil.const -> string
@ -64,17 +64,17 @@ val type_get_annotation : Sil.typ -> Sil.item_annotation option
(** Get the class name of the type *) (** Get the class name of the type *)
val type_get_class_name : Sil.typ -> Mangled.t option val type_get_class_name : Sil.typ -> Mangled.t option
val type_get_direct_supertypes : Sil.typ -> Mangled.t list val type_get_direct_supertypes : Sil.typ -> Typename.t list
(** Is the type a class with the given name *) (** Is the type a class with the given name *)
val type_has_class_name : Sil.typ -> Mangled.t -> bool val type_has_class_name : Sil.typ -> Mangled.t -> bool
val type_has_direct_supertype : Sil.typ -> Mangled.t -> bool val type_has_direct_supertype : Sil.typ -> Typename.t -> bool
(** Is the type a class type *) (** Is the type a class type *)
val type_is_class : Sil.typ -> bool val type_is_class : Sil.typ -> bool
val type_is_nested_in_direct_supertype : Sil.typ -> Mangled.t -> bool val type_is_nested_in_direct_supertype : Sil.typ -> Typename.t -> bool
val type_is_nested_in_type : Sil.typ -> Mangled.t -> bool val type_is_nested_in_type : Sil.typ -> Mangled.t -> bool

@ -119,7 +119,7 @@ let create_curr_class tenv class_name =
let class_tn_name = Typename.TN_csu (Csu.Class, (Mangled.from_string class_name)) in let class_tn_name = Typename.TN_csu (Csu.Class, (Mangled.from_string class_name)) in
match Sil.tenv_lookup tenv class_tn_name with match Sil.tenv_lookup tenv class_tn_name with
| Some Sil.Tstruct(intf_fields, _, _, _, superclasses, methods, annotation) -> | Some Sil.Tstruct(intf_fields, _, _, _, superclasses, methods, annotation) ->
(let superclasses_names = IList.map (fun (_, name) -> Mangled.to_string name) superclasses in (let superclasses_names = IList.map Typename.name superclasses in
match superclasses_names with match superclasses_names with
| superclass:: protocols -> | superclass:: protocols ->
ContextCls (class_name, Some superclass, protocols) ContextCls (class_name, Some superclass, protocols)

@ -20,8 +20,8 @@ let rec get_fields_super_classes tenv super_class =
Printing.log_out " ... Getting fields of superclass '%s'\n" (Typename.to_string super_class); Printing.log_out " ... Getting fields of superclass '%s'\n" (Typename.to_string super_class);
match Sil.tenv_lookup tenv super_class with match Sil.tenv_lookup tenv super_class with
| None -> [] | None -> []
| Some Sil.Tstruct (fields, _, _, _, (Csu.Class, sc):: _, _, _) -> | Some Sil.Tstruct (fields, _, _, _, super_class :: _, _, _) ->
let sc_fields = get_fields_super_classes tenv (Typename.TN_csu (Csu.Class, sc)) in let sc_fields = get_fields_super_classes tenv super_class in
General_utils.append_no_duplicates_fields fields sc_fields General_utils.append_no_duplicates_fields fields sc_fields
| Some Sil.Tstruct (fields, _, _, _, _, _, _) -> fields | Some Sil.Tstruct (fields, _, _, _, _, _, _) -> fields
| Some _ -> [] | Some _ -> []

@ -48,9 +48,8 @@ struct
| Sil.Tstruct (fields, _, _, cls, super_classes, methods, iann) -> | Sil.Tstruct (fields, _, _, cls, super_classes, methods, iann) ->
print_endline ( print_endline (
(Typename.to_string typname) ^ "\n"^ (Typename.to_string typname) ^ "\n"^
"---> superclass and protocols " ^ (IList.to_string (fun (csu, x) -> "---> superclass and protocols " ^ (IList.to_string (fun tn ->
let nsu = Typename.TN_csu (csu, x) in "\t" ^ (Typename.to_string tn) ^ "\n") super_classes) ^
"\t" ^ (Typename.to_string nsu) ^ "\n") super_classes) ^
"---> methods " ^ "---> methods " ^
(IList.to_string (fun x ->"\t" ^ (Procname.to_string x) ^ "\n") methods) (IList.to_string (fun x ->"\t" ^ (Procname.to_string x) ^ "\n") methods)
^ " " ^ ^ " " ^
@ -430,10 +429,7 @@ struct
| [] -> list1 | [] -> list1
let append_no_duplicates_csu list1 list2 = let append_no_duplicates_csu list1 list2 =
append_no_duplicates append_no_duplicates Typename.equal list1 list2
(fun (ds1, n1) (ds2, n2) ->
Csu.equal ds1 ds2 && Mangled.equal n1 n2)
list1 list2
let append_no_duplicates_methods list1 list2 = let append_no_duplicates_methods list1 list2 =
append_no_duplicates Procname.equal list1 list2 append_no_duplicates Procname.equal list1 list2

@ -139,7 +139,7 @@ sig
(Ident.fieldname * Sil.typ * Sil.item_annotation) list -> (Ident.fieldname * Sil.typ * Sil.item_annotation) list (Ident.fieldname * Sil.typ * Sil.item_annotation) list -> (Ident.fieldname * Sil.typ * Sil.item_annotation) list
val append_no_duplicates_csu : val append_no_duplicates_csu :
(Csu.t * Mangled.t) list -> (Csu.t * Mangled.t) list -> (Csu.t * Mangled.t) list Typename.t list -> Typename.t list -> Typename.t list
val append_no_duplicates_methods : Procname.t list -> Procname.t list -> Procname.t list val append_no_duplicates_methods : Procname.t list -> Procname.t list -> Procname.t list

@ -191,8 +191,8 @@ let get_superclass_curr_class context =
let iname = Typename.TN_csu (Csu.Class, Mangled.from_string cname) in let iname = Typename.TN_csu (Csu.Class, Mangled.from_string cname) in
Printing.log_out "Checking for superclass = '%s'\n\n%!" (Typename.to_string iname); Printing.log_out "Checking for superclass = '%s'\n\n%!" (Typename.to_string iname);
match Sil.tenv_lookup (CContext.get_tenv context) iname with match Sil.tenv_lookup (CContext.get_tenv context) iname with
| Some Sil.Tstruct(_, _, _, _, (_, super_name):: _, _, _) -> | Some Sil.Tstruct(_, _, _, _, super_name :: _, _, _) ->
Mangled.to_string super_name Typename.name super_name
| _ -> | _ ->
Printing.log_err "NOT FOUND superclass = '%s'\n\n%!" (Typename.to_string iname); Printing.log_err "NOT FOUND superclass = '%s'\n\n%!" (Typename.to_string iname);
(match super_opt with (match super_opt with

@ -143,7 +143,7 @@ let get_superclass_decls decl =
let get_superclass_list decl = let get_superclass_list decl =
let base_decls = get_superclass_decls decl in let base_decls = get_superclass_decls decl in
let decl_to_mangled_name decl = Mangled.from_string (get_record_name decl) in let decl_to_mangled_name decl = Mangled.from_string (get_record_name decl) in
let get_super_field super_decl = (Csu.Class, decl_to_mangled_name super_decl) in let get_super_field super_decl = Typename.TN_csu (Csu.Class, decl_to_mangled_name super_decl) in
IList.map get_super_field base_decls IList.map get_super_field base_decls
let add_struct_to_tenv tenv typ = let add_struct_to_tenv tenv typ =

@ -92,9 +92,9 @@ let get_interface_superclasses super_opt protocols =
let super_class = let super_class =
match super_opt with match super_opt with
| None -> [] | None -> []
| Some super -> [(Csu.Class, Mangled.from_string super)] in | Some super -> [Typename.TN_csu (Csu.Class, Mangled.from_string super)] in
let protocol_names = IList.map ( let protocol_names = IList.map (
fun name -> (Csu.Protocol, Mangled.from_string name) fun name -> Typename.TN_csu (Csu.Protocol, Mangled.from_string name)
) protocols in ) protocols in
let super_classes = super_class@protocol_names in let super_classes = super_class@protocol_names in
super_classes super_classes
@ -123,9 +123,9 @@ let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info class_name
Printing.log_out "----->SuperClass field: '%s' " (Ident.fieldname_to_string fn); Printing.log_out "----->SuperClass field: '%s' " (Ident.fieldname_to_string fn);
Printing.log_out "type: '%s'\n" (Sil.typ_to_string ft)) fields_sc; Printing.log_out "type: '%s'\n" (Sil.typ_to_string ft)) fields_sc;
(*In case we found categories, or partial definition of this class earlier and they are already in the tenv *) (*In case we found categories, or partial definition of this class earlier and they are already in the tenv *)
let fields, superclasses, methods = let fields, (superclasses : Typename.t list), methods =
match Sil.tenv_lookup tenv interface_name with match Sil.tenv_lookup tenv interface_name with
| Some Sil.Tstruct(saved_fields, _, _, _, saved_superclasses, saved_methods, _) -> | Some (Sil.Tstruct (saved_fields, _, _, _, saved_superclasses, saved_methods, _)) ->
General_utils.append_no_duplicates_fields fields saved_fields, General_utils.append_no_duplicates_fields fields saved_fields,
General_utils.append_no_duplicates_csu superclasses saved_superclasses, General_utils.append_no_duplicates_csu superclasses saved_superclasses,
General_utils.append_no_duplicates_methods methods saved_methods General_utils.append_no_duplicates_methods methods saved_methods

@ -255,14 +255,15 @@ let get_all_supertypes typ tenv =
let get_direct_supers = function let get_direct_supers = function
| Sil.Tstruct (_, _, Csu.Class, _, supers, _, _) -> supers | Sil.Tstruct (_, _, Csu.Class, _, supers, _, _) -> supers
| _ -> [] in | _ -> [] in
let rec add_typ name typs = let rec add_typ class_name typs =
let typename = Typename.TN_csu (Csu.Class, name) in match Sil.tenv_lookup tenv class_name with
match Sil.tenv_lookup tenv typename with
| Some typ -> get_supers_rec typ tenv (TypSet.add typ typs) | Some typ -> get_supers_rec typ tenv (TypSet.add typ typs)
| None -> typs | None -> typs
and get_supers_rec typ tenv all_supers = and get_supers_rec typ tenv all_supers =
let direct_supers = get_direct_supers typ in let direct_supers = get_direct_supers typ in
IList.fold_left (fun typs (_, name) -> add_typ name typs) all_supers direct_supers in IList.fold_left
(fun typs class_name -> add_typ class_name typs)
all_supers direct_supers in
get_supers_rec typ tenv (TypSet.add typ TypSet.empty) get_supers_rec typ tenv (TypSet.add typ TypSet.empty)
(** return true if [typ0] <: [typ1] *) (** return true if [typ0] <: [typ1] *)
@ -305,7 +306,7 @@ let typ_is_lifecycle_typ typ lifecycle_typ tenv =
(** return true if [class_name] is the name of a class that belong to the Android framework *) (** 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 is_android_lib_class class_name =
let class_str = Mangled.to_string class_name in let class_str = Typename.name class_name in
string_is_prefix "android" class_str || string_is_prefix "com.android" class_str string_is_prefix "android" class_str || string_is_prefix "com.android" class_str
(** returns an option containing the var name and type of a callback registered by [procname], None (** returns an option containing the var name and type of a callback registered by [procname], None
@ -378,10 +379,8 @@ let get_lifecycles = android_lifecycles
let is_runtime_exception tenv exn = let is_runtime_exception tenv exn =
let lookup = Sil.tenv_lookup tenv in let lookup = Sil.tenv_lookup tenv in
let runtime_exception_typename = let runtime_exception_typename =
let name = Mangled.from_package_class "java.lang" "RuntimeException" in Typename.Java.from_string "java.lang.RuntimeException" in
Typename.TN_csu (Csu.Class, name) match lookup runtime_exception_typename, lookup exn with
and exn_typename = Typename.TN_csu (Csu.Class, exn) in
match lookup runtime_exception_typename, lookup exn_typename with
| Some runtime_exception_type, Some exn_type -> | Some runtime_exception_type, Some exn_type ->
is_subtype exn_type runtime_exception_type tenv is_subtype exn_type runtime_exception_type tenv
| _ -> false | _ -> false

@ -47,10 +47,10 @@ val get_callbacks_registered_by_proc : Cfg.Procdesc.t -> Sil.tenv -> Sil.typ lis
val get_lifecycle_for_framework_typ_opt : Mangled.t -> string list -> Sil.tenv -> (Sil.typ * Procname.t list) option val get_lifecycle_for_framework_typ_opt : Mangled.t -> string list -> Sil.tenv -> (Sil.typ * Procname.t list) option
(** return true if [class_name] is the name of a class that belong to the Android framework *) (** return true if [class_name] is the name of a class that belong to the Android framework *)
val is_android_lib_class : Mangled.t -> bool val is_android_lib_class : Typename.t -> bool
(** Path to the android.jar file containing real code, not just the method stubs as in the SDK *) (** Path to the android.jar file containing real code, not just the method stubs as in the SDK *)
val non_stub_android_jar : unit -> string val non_stub_android_jar : unit -> string
(** [is_runtime_exception tenv exn] checks if exn is an unchecked exception *) (** [is_runtime_exception tenv exn] checks if exn is an unchecked exception *)
val is_runtime_exception : Sil.tenv -> Mangled.t -> bool val is_runtime_exception : Sil.tenv -> Typename.t -> bool

@ -53,7 +53,7 @@ let extract_callbacks procdesc cfg_file cfg tenv harness_name harness_lvar callb
| l -> | l ->
(* choose to describe this anonymous inner class with one of the interfaces that it (* choose to describe this anonymous inner class with one of the interfaces that it
* implements. translation always places interfaces at the end of the supertypes list *) * implements. translation always places interfaces at the end of the supertypes list *)
Mangled.get_mangled (IList.hd (IList.rev l)) Typename.name (IList.hd (IList.rev l))
else typ_str in else typ_str in
Mangled.from_string (pretty_typ_str ^ "[line " ^ Location.to_string loc ^ "]") in Mangled.from_string (pretty_typ_str ^ "[line " ^ Location.to_string loc ^ "]") in
let create_instrumentation_fields created_flds node instr = match instr with let create_instrumentation_fields created_flds node instr = match instr with
@ -118,16 +118,19 @@ let find_registered_callbacks lifecycle_trace harness_name proc_file_map tenv =
(** if [typ] is a lifecycle type, generate a list of (method call, receiver) pairs constituting a (** if [typ] is a lifecycle type, generate a list of (method call, receiver) pairs constituting a
lifecycle trace *) lifecycle trace *)
let try_create_lifecycle_trace typ lifecycle_typ lifecycle_procs proc_file_map tenv = match typ with let try_create_lifecycle_trace typ lifecycle_typ lifecycle_procs proc_file_map tenv = match typ with
| Sil.Tstruct(_, _, Csu.Class, Some class_name, _, methods, _) | Sil.Tstruct(_, _, Csu.Class, Some name, _, methods, _) ->
when AndroidFramework.typ_is_lifecycle_typ typ lifecycle_typ tenv && let class_name = Typename.TN_csu (Csu.Class, name) in
not (AndroidFramework.is_android_lib_class class_name) -> if AndroidFramework.typ_is_lifecycle_typ typ lifecycle_typ tenv &&
let ptr_to_typ = Some (Sil.Tptr (typ, Sil.Pk_pointer)) in not (AndroidFramework.is_android_lib_class class_name) then
IList.fold_left (fun trace lifecycle_proc -> let ptr_to_typ = Some (Sil.Tptr (typ, Sil.Pk_pointer)) in
(* given a lifecycle subclass T, resolve the call T.lifecycle_proc() to the procname IList.fold_left
* that will actually be called at runtime *) (fun trace lifecycle_proc ->
let resolved_proc = SymExec.resolve_method tenv class_name lifecycle_proc in (* given a lifecycle subclass T, resolve the call T.lifecycle_proc() to the procname
(resolved_proc, ptr_to_typ) :: trace * that will actually be called at runtime *)
) [] lifecycle_procs let resolved_proc = SymExec.resolve_method tenv class_name lifecycle_proc in
(resolved_proc, ptr_to_typ) :: trace)
[] lifecycle_procs
else []
| _ -> [] | _ -> []
(** get all the callbacks registered in [lifecycle_trace], transform the SIL to "extract" them into (** get all the callbacks registered in [lifecycle_trace], transform the SIL to "extract" them into

@ -306,15 +306,12 @@ and create_sil_type program tenv cn =
| None -> dummy_type cn | None -> dummy_type cn
| Some node -> | Some node ->
let create_super_list interface_names = let create_super_list interface_names =
(IList.map (fun i -> Mangled.from_string (JBasics.cn_name i)) interface_names) in IList.map typename_of_classname interface_names in
let (super_list, nonstatic_fields, static_fields, item_annotation) = let (super_list, nonstatic_fields, static_fields, item_annotation) =
match node with match node with
| Javalib.JInterface jinterface -> | Javalib.JInterface jinterface ->
let static_fields, _ = get_all_fields program tenv cn in let static_fields, _ = get_all_fields program tenv cn in
let sil_interface_list = let sil_interface_list = create_super_list jinterface.Javalib.i_interfaces in
IList.map
(fun c -> (Csu.Class, c))
(create_super_list jinterface.Javalib.i_interfaces) in
let item_annotation = JAnnotation.translate_item jinterface.Javalib.i_annotations in let item_annotation = JAnnotation.translate_item jinterface.Javalib.i_annotations in
(sil_interface_list, [], static_fields, item_annotation) (sil_interface_list, [], static_fields, item_annotation)
| Javalib.JClass jclass -> | Javalib.JClass jclass ->
@ -329,12 +326,11 @@ and create_sil_type program tenv cn =
| Some super_cn -> | Some super_cn ->
let super_classname = let super_classname =
match get_class_type_no_pointer program tenv super_cn with match get_class_type_no_pointer program tenv super_cn with
| Sil.Tstruct (_, _, _, Some classname, _, _, _) -> classname | Sil.Tstruct (_, _, _, Some classname, _, _, _) ->
Typename.TN_csu (Csu.Class, classname)
| _ -> assert false in | _ -> assert false in
super_classname :: interface_list in super_classname :: interface_list in
let super_sil_classname_list = (super_classname_list, nonstatic_fields, static_fields, item_annotation) in
IList.map (fun c -> (Csu.Class, c)) super_classname_list in
(super_sil_classname_list, nonstatic_fields, static_fields, item_annotation) in
let classname = Mangled.from_string (JBasics.cn_name cn) in let classname = Mangled.from_string (JBasics.cn_name cn) in
let method_procnames = get_class_procnames cn node in let method_procnames = get_class_procnames cn node in
Sil.Tstruct (nonstatic_fields, static_fields, Csu.Class, Sil.Tstruct (nonstatic_fields, static_fields, Csu.Class,

Loading…
Cancel
Save