From 5190f12cc1ec529dabdedab5468d6b1a25e2f428 Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Wed, 3 Jun 2020 06:35:07 -0700 Subject: [PATCH] [inferbo] Add model of class.getFields Summary: The model returns an array the length of which is the number of known fields in `tenv`. Reviewed By: ezgicicek Differential Revision: D21840375 fbshipit-source-id: 891517c6e --- .../src/bufferoverrun/bufferOverrunModels.ml | 34 +++++++++++++++++++ .../java/performance/IteratorTest.java | 11 ++++++ .../java/performance/cost-issues.exp | 2 ++ .../codetoanalyze/java/performance/issues.exp | 4 +-- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/infer/src/bufferoverrun/bufferOverrunModels.ml b/infer/src/bufferoverrun/bufferOverrunModels.ml index 499be45de..7b80e5029 100644 --- a/infer/src/bufferoverrun/bufferOverrunModels.ml +++ b/infer/src/bufferoverrun/bufferOverrunModels.ml @@ -1055,6 +1055,39 @@ module Collection = struct {exec; check= check_index ~last_included:false coll_id index_exp} end +module JavaClass = struct + let get_fields class_name_exp = + let exec {pname; node_hash; location; tenv} ~ret:(ret_id, _) mem = + match class_name_exp with + | Exp.Const (Const.Cclass name) -> ( + let typ_name = Typ.Name.Java.from_string (Ident.name_to_string name) in + match Tenv.lookup tenv typ_name with + | Some {fields} -> + let loc = + Allocsite.make pname ~node_hash ~inst_num:0 ~dimension:1 ~path:None + ~represents_multiple_values:true + |> Loc.of_allocsite + in + let arr_v = + let allocsite = + Allocsite.make pname ~node_hash ~inst_num:1 ~dimension:1 ~path:None + ~represents_multiple_values:true + in + let length = List.length fields |> Itv.of_int in + let traces = Trace.(Set.singleton location ArrayDeclaration) in + Dom.Val.of_java_array_alloc allocsite ~length ~traces + in + Dom.Mem.add_heap loc arr_v mem |> model_by_value (Dom.Val.of_loc loc) ret_id + | None -> + Logging.d_printfln_escaped "Could not find class from tenv" ; + mem ) + | _ -> + Logging.d_printfln_escaped "Parameter is not a class name constant" ; + mem + in + {exec; check= no_check} +end + module JavaString = struct let fn = BufferOverrunField.java_collection_internal_array @@ -1530,6 +1563,7 @@ module Call = struct &:: "substring" <>$ any_arg $+ capt_exp $+ capt_exp $--> JavaString.substring ; +PatternMatch.implements_lang "Class" &:: "getCanonicalName" &::.*--> JavaString.inferbo_constant_string + ; +PatternMatch.implements_lang "Class" &:: "getFields" <>$ capt_exp $--> JavaClass.get_fields ; +PatternMatch.implements_lang "Enum" &:: "name" &::.*--> JavaString.inferbo_constant_string ; +PatternMatch.implements_lang "Integer" &:: "intValue" <>$ capt_exp $--> JavaInteger.intValue diff --git a/infer/tests/codetoanalyze/java/performance/IteratorTest.java b/infer/tests/codetoanalyze/java/performance/IteratorTest.java index b05fdeff4..e628f1a41 100644 --- a/infer/tests/codetoanalyze/java/performance/IteratorTest.java +++ b/infer/tests/codetoanalyze/java/performance/IteratorTest.java @@ -4,8 +4,15 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ + +import java.lang.reflect.Field; import java.util.Iterator; +class MyClassWithFields { + int x; + int y; +} + public class IteratorTest { public void appendTo(Iterator parts) { @@ -32,4 +39,8 @@ public class IteratorTest { public void enum_iter() { for (Color c : Color.values()) {} } + + public void fields_iter() { + for (Field f : MyClassWithFields.class.getFields()) {} + } } diff --git a/infer/tests/codetoanalyze/java/performance/cost-issues.exp b/infer/tests/codetoanalyze/java/performance/cost-issues.exp index 4d72f6405..b714aa8bc 100644 --- a/infer/tests/codetoanalyze/java/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/java/performance/cost-issues.exp @@ -211,7 +211,9 @@ codetoanalyze/java/performance/IteratorTest.java, IteratorTest$Color.values():It codetoanalyze/java/performance/IteratorTest.java, IteratorTest.(), 3, OnUIThread:false codetoanalyze/java/performance/IteratorTest.java, IteratorTest.appendTo(java.util.Iterator):void, 3 + 10 ⋅ parts.length + 3 ⋅ (parts.length + 1), OnUIThread:false codetoanalyze/java/performance/IteratorTest.java, IteratorTest.enum_iter():void, 43, OnUIThread:false +codetoanalyze/java/performance/IteratorTest.java, IteratorTest.fields_iter():void, 28, OnUIThread:false codetoanalyze/java/performance/IteratorTest.java, IteratorTest.linearIterable(java.lang.Iterable):void, 9 + 10 ⋅ elements.length + 3 ⋅ (elements.length + 1), OnUIThread:false +codetoanalyze/java/performance/IteratorTest.java, MyClassWithFields.(), 3, OnUIThread:false codetoanalyze/java/performance/JsonArray.java, libraries.marauder.analytics.utils.json.JsonArray.(), 9, OnUIThread:false codetoanalyze/java/performance/JsonArray.java, libraries.marauder.analytics.utils.json.JsonArray.addStringEntry(java.lang.String):void, ⊤, OnUIThread:false codetoanalyze/java/performance/JsonMap.java, libraries.marauder.analytics.utils.json.JsonMap.(), 9, OnUIThread:false diff --git a/infer/tests/codetoanalyze/java/performance/issues.exp b/infer/tests/codetoanalyze/java/performance/issues.exp index be6e64685..e7b708002 100644 --- a/infer/tests/codetoanalyze/java/performance/issues.exp +++ b/infer/tests/codetoanalyze/java/performance/issues.exp @@ -142,8 +142,8 @@ codetoanalyze/java/performance/Invariant.java, Invariant.formal_not_invariant_FP codetoanalyze/java/performance/Invariant.java, Invariant.list_size_invariant(java.util.List):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 2 + 5 ⋅ items.length + 3 ⋅ (items.length + 1), O(items.length), degree = 1,{items.length + 1},Loop at line 66,{items.length},Loop at line 66] codetoanalyze/java/performance/Invariant.java, Invariant.local_not_invariant_FP(int):void, 3, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 3 + 12 ⋅ (size + 5) + 7 ⋅ (size + 5) × (5+min(1, size)) + 4 ⋅ (5+min(0, size)), O(size²), degree = 2,{5+min(0, size)},Loop at line 46,{5+min(1, size)},Loop at line 46,{size + 5},Loop at line 46] codetoanalyze/java/performance/Invariant.java, Invariant.x_is_invariant_ok(int):void, 7, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 8 + 6 ⋅ (size + 20), O(size), degree = 1,{size + 20},Loop at line 19] -codetoanalyze/java/performance/IteratorTest.java, IteratorTest.appendTo(java.util.Iterator):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 1 + 10 ⋅ parts.length + 3 ⋅ (parts.length + 1), O(parts.length), degree = 1,{parts.length + 1},Loop at line 12,{parts.length},Loop at line 12] -codetoanalyze/java/performance/IteratorTest.java, IteratorTest.linearIterable(java.lang.Iterable):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 9 + 10 ⋅ elements.length + 3 ⋅ (elements.length + 1), O(elements.length), degree = 1,{elements.length + 1},call to void IteratorTest.appendTo(Iterator),Loop at line 12,{elements.length},call to void IteratorTest.appendTo(Iterator),Loop at line 12] +codetoanalyze/java/performance/IteratorTest.java, IteratorTest.appendTo(java.util.Iterator):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 1 + 10 ⋅ parts.length + 3 ⋅ (parts.length + 1), O(parts.length), degree = 1,{parts.length + 1},Loop at line 19,{parts.length},Loop at line 19] +codetoanalyze/java/performance/IteratorTest.java, IteratorTest.linearIterable(java.lang.Iterable):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 9 + 10 ⋅ elements.length + 3 ⋅ (elements.length + 1), O(elements.length), degree = 1,{elements.length + 1},call to void IteratorTest.appendTo(Iterator),Loop at line 19,{elements.length},call to void IteratorTest.appendTo(Iterator),Loop at line 19] codetoanalyze/java/performance/JsonArray.java, libraries.marauder.analytics.utils.json.JsonArray.addStringEntry(java.lang.String):void, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to void JsonUtils.serialize(StringBuilder,String),Call to void JsonUtils.escape(StringBuilder,String),Unbounded loop,Loop at line 13] codetoanalyze/java/performance/JsonMap.java, libraries.marauder.analytics.utils.json.JsonMap.addEntry(java.lang.String,boolean):void, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to void JsonMap.addKeyToMap(String),Call to void JsonUtils.serialize(StringBuilder,String),Call to void JsonUtils.escape(StringBuilder,String),Unbounded loop,Loop at line 13] codetoanalyze/java/performance/JsonMap.java, libraries.marauder.analytics.utils.json.JsonMap.addEntry(java.lang.String,double):void, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to void JsonMap.addKeyToMap(String),Call to void JsonUtils.serialize(StringBuilder,String),Call to void JsonUtils.escape(StringBuilder,String),Unbounded loop,Loop at line 13]