[inferbo] Add model of Class.getCanonicalName

Summary: Similarly to Enum.name, we model Class.getCanonicalName as returning an arbitrary non-empty string.

Reviewed By: ngorogiannis

Differential Revision: D21207120

fbshipit-source-id: 1e2dbd1fd
master
Sungkeun Cho 5 years ago committed by Facebook GitHub Bot
parent 0b6c5172a8
commit 3aaf260b8b

@ -522,10 +522,15 @@ module ArrObjCommon = struct
Sem.eval_array_locs_length (deref_of model_env exp ~fn mem) mem
let size_exec exp ~fn model_env ~ret:(id, _) mem =
let arr_locs = deref_of model_env exp ~fn mem in
let mem = Dom.Mem.add_stack (Loc.of_id id) (Sem.eval_array_locs_length arr_locs mem) mem in
load_size_alias id arr_locs mem
let size_exec exp ~fn ({integer_type_widths} as model_env) ~ret:(id, _) mem =
let locs = Sem.eval integer_type_widths exp mem |> Dom.Val.get_all_locs in
match PowLoc.is_singleton_or_more locs with
| Singleton (Loc.Allocsite (Allocsite.LiteralString s)) ->
model_by_value (Dom.Val.of_int (String.length s)) id mem
| _ ->
let arr_locs = deref_of model_env exp ~fn mem in
let mem = Dom.Mem.add_stack (Loc.of_id id) (Sem.eval_array_locs_length arr_locs mem) mem in
load_size_alias id arr_locs mem
let at arr_exp ~fn index_exp =
@ -1183,18 +1188,16 @@ module JavaString = struct
{exec; check= no_check}
let copy_constructor_constant tgt_exp s = copy_constructor tgt_exp (Exp.Const (Const.Cstr s))
let empty_constructor tgt_exp = copy_constructor_constant tgt_exp ""
let empty_constructor tgt_exp = copy_constructor tgt_exp (Exp.Const (Const.Cstr ""))
(* We model Enum.name as returing a constant name, rather than getting real field names. We did
this because we couldn't think of any big gains from getting the real names. *)
let enum_name tgt_exp =
let {exec= constructor_exec} = copy_constructor_constant tgt_exp "EnumName" in
let exec ({integer_type_widths} as model_env) ~ret:((ret_id, _) as ret) mem =
let v = Sem.eval integer_type_widths tgt_exp mem in
constructor_exec model_env ~ret mem |> model_by_value v ret_id
(* We model Enum.name or Class.getCanonicalName as returning an arbitrary constant name, rather
than getting real names. We did this because we couldn't think of any big gains from getting
the real names in terms of analysis precision. *)
let inferbo_constant_string =
let constant_string_val =
Loc.of_allocsite (Allocsite.literal_string "__constant_string") |> Dom.Val.of_loc
in
let exec _model_env ~ret:(ret_id, _) mem = model_by_value constant_string_val ret_id mem in
{exec; check= no_check}
@ -1564,5 +1567,7 @@ module Call = struct
; +PatternMatch.implements_lang "Math"
&:: "min" <>$ capt_exp $+ capt_exp
$--> eval_binop ~f:(Itv.min_sem ~use_minmax_bound:true)
; +PatternMatch.implements_lang "Enum" &:: "name" <>$ capt_exp $--> JavaString.enum_name ]
; +PatternMatch.implements_lang "Enum" &:: "name" &::.*--> JavaString.inferbo_constant_string
; +PatternMatch.implements_lang "Class"
&:: "getCanonicalName" &::.*--> JavaString.inferbo_constant_string ]
end

@ -108,4 +108,8 @@ class StringTest {
i = j;
}
}
void class_get_canonical_name_constant(Integer a) {
for (int i = 0; i < a.getClass().getCanonicalName().length(); i++) {}
}
}

@ -194,6 +194,8 @@ codetoanalyze/java/performance/PreconditionTest.java, PreconditionTest.checkNotN
codetoanalyze/java/performance/StringBuilderTest.java, StringBuilderTest.append_linear(java.lang.String):void, 2, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 25 + 5 ⋅ (s.length + 2) + 3 ⋅ (s.length + 3), O(s.length), degree = 1,{s.length + 3},call to void StringBuilderTest.new_linear(String),Loop at line 13,{s.length + 2},call to void StringBuilderTest.new_linear(String),Loop at line 13]
codetoanalyze/java/performance/StringBuilderTest.java, StringBuilderTest.new_linear(java.lang.String):void, 2, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 9 + 5 ⋅ s.length + 3 ⋅ (s.length + 1), O(s.length), degree = 1,{s.length + 1},Loop at line 13,{s.length},Loop at line 13]
codetoanalyze/java/performance/StringTest.java, StringTest.byte_array_constructor_linear(byte[]):void, 2, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 6 + 5 ⋅ data.length + 3 ⋅ (data.length + 1), O(data.length), degree = 1,{data.length + 1},Loop at line 55,{data.length},Loop at line 55]
codetoanalyze/java/performance/StringTest.java, StringTest.class_get_canonical_name_constant(java.lang.Integer):void, 1, BUFFER_OVERRUN_U5, no_bucket, ERROR, [<Length trace>,Unknown value from: Class Object.getClass(),Assignment,Array access: Offset: [-oo, +oo] Size: [0, +oo]]
codetoanalyze/java/performance/StringTest.java, StringTest.class_get_canonical_name_constant(java.lang.Integer):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 249, O(1), degree = 0]
codetoanalyze/java/performance/StringTest.java, StringTest.index_substring_linear():java.lang.String, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 9 + this.mId.length, O(this.mId.length), degree = 1,{this.mId.length},call to int StringTest.indexof_linear(String),Modeled call to String.indexOf]
codetoanalyze/java/performance/StringTest.java, StringTest.indexof_from_linear(java.lang.String,int):int, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 3 + (-j + m.length), O((-j + m.length)), degree = 1,{-j + m.length},Modeled call to String.indexOf]
codetoanalyze/java/performance/StringTest.java, StringTest.indexof_linear(java.lang.String):int, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 2 + m.length, O(m.length), degree = 1,{m.length},Modeled call to String.indexOf]

Loading…
Cancel
Save