diff --git a/infer/src/bufferoverrun/bufferOverrunModels.ml b/infer/src/bufferoverrun/bufferOverrunModels.ml index 213eeb88a..8d65a45a9 100644 --- a/infer/src/bufferoverrun/bufferOverrunModels.ml +++ b/infer/src/bufferoverrun/bufferOverrunModels.ml @@ -680,7 +680,7 @@ module Collection = struct {exec; check= no_check} - let new_collection _ = + let new_collection = let exec = create_collection ~length:Itv.zero in {exec; check= no_check} @@ -710,9 +710,9 @@ module Collection = struct let add coll_id = {exec= change_size_by ~size_f:Itv.incr coll_id; check= no_check} - let singleton_collection el_var = + let singleton_collection = let exec env ~ret:((id, _) as ret) mem = - let {exec= new_exec; check= _} = new_collection el_var in + let {exec= new_exec; check= _} = new_collection in let mem = new_exec env ~ret mem in change_size_by ~size_f:Itv.incr id ~ret env mem in @@ -862,17 +862,17 @@ module Call = struct ; -"malloc" <>$ capt_exp $+...$--> malloc ~can_be_zero:false ; -"calloc" <>$ capt_exp $+ capt_exp $!--> calloc ~can_be_zero:false ; -"__new" - <>$ capt_exp_of_typ (+PatternMatch.implements_pseudo_collection) + <>$ any_arg_of_typ (+PatternMatch.implements_pseudo_collection) $+...$--> Collection.new_collection ; -"__new" - <>$ capt_exp_of_typ (+PatternMatch.implements_collection) + <>$ any_arg_of_typ (+PatternMatch.implements_collection) $+...$--> Collection.new_collection ; -"__new" - <>$ capt_exp_of_typ (+PatternMatch.implements_map) + <>$ any_arg_of_typ (+PatternMatch.implements_map) $+...$--> Collection.new_collection ; +PatternMatch.implements_map &:: "size" <>$ capt_exp $!--> Collection.size ; -"__new" - <>$ capt_exp_of_typ (+PatternMatch.implements_org_json "JSONArray") + <>$ any_arg_of_typ (+PatternMatch.implements_org_json "JSONArray") $+...$--> Collection.new_collection ; -"__new" <>$ capt_exp $+...$--> malloc ~can_be_zero:true ; -"__new_array" <>$ capt_exp $+...$--> malloc ~can_be_zero:true @@ -961,15 +961,13 @@ module Call = struct (* model sets as lists *) ; +PatternMatch.implements_collections &::+ unmodifiable <>$ capt_exp $--> Collection.iterator - ; +PatternMatch.implements_collections - &:: "singleton" <>$ capt_exp $--> Collection.singleton_collection - ; +PatternMatch.implements_collections - &:: "emptySet" <>$ capt_exp $--> Collection.new_collection + ; +PatternMatch.implements_collections &:: "singleton" <>--> Collection.singleton_collection + ; +PatternMatch.implements_collections &:: "emptySet" <>--> Collection.new_collection (* model maps as lists *) ; +PatternMatch.implements_collections - &:: "singletonMap" <>$ capt_exp $--> Collection.singleton_collection + &:: "singletonMap" <>--> Collection.singleton_collection ; +PatternMatch.implements_collections - &:: "singletonList" <>$ capt_exp $--> Collection.singleton_collection + &:: "singletonList" <>--> Collection.singleton_collection ; +PatternMatch.implements_collection &:: "get" <>$ capt_var_exn $+ capt_exp $--> Collection.get_or_set_at_index ; +PatternMatch.implements_collection diff --git a/infer/tests/codetoanalyze/java/performance/CollectionsTest.java b/infer/tests/codetoanalyze/java/performance/CollectionsTest.java index 45c70a778..c839d82b8 100644 --- a/infer/tests/codetoanalyze/java/performance/CollectionsTest.java +++ b/infer/tests/codetoanalyze/java/performance/CollectionsTest.java @@ -60,4 +60,9 @@ class CollectionsTest { void unmodifiable_set(Set set) { for (Integer el : Collections.unmodifiableSet(set)) {} } + + void emptySet_zero() { + Set set = Collections.emptySet(); + for (String s : set) {} + } } diff --git a/infer/tests/codetoanalyze/java/performance/issues.exp b/infer/tests/codetoanalyze/java/performance/issues.exp index ec87add98..664c25fce 100644 --- a/infer/tests/codetoanalyze/java/performance/issues.exp +++ b/infer/tests/codetoanalyze/java/performance/issues.exp @@ -67,6 +67,9 @@ codetoanalyze/java/performance/CollectionTest.java, CollectionTest.nested_iterat codetoanalyze/java/performance/CollectionTest.java, CollectionTest.sparse_array_linear(android.util.SparseArray):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 2 + 5 ⋅ arr.length + 3 ⋅ (arr.length + 1), degree = 1,{arr.length + 1},Loop at line 64,{arr.length},Loop at line 64] codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.binary_search_log(java.util.List):int, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 2 + log(list.length), degree = 0 + 1⋅log,{list.length},Modeled call to Collections.binarySearch] codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.copy_linear(java.util.List,java.util.List):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 3 + list_to.length, degree = 1,{list_to.length},Modeled call to Collections.copy] +codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.emptySet_zero():void, 0, ZERO_EXECUTION_TIME, no_bucket, ERROR, [] +codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.emptySet_zero():void, 2, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, [Here] +codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.emptySet_zero():void, 2, CONDITION_ALWAYS_TRUE, no_bucket, WARNING, [Here] codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.fill_linear(java.util.List,java.lang.String):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 3 + list.length, degree = 1,{list.length},Modeled call to Collections.fill] codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.reverse_linear(java.util.List):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 2 + list.length, degree = 1,{list.length},Modeled call to Collections.reverse] codetoanalyze/java/performance/CollectionsTest.java, CollectionsTest.shuffle_linear(java.util.List,java.util.Random):void, 1, EXPENSIVE_EXECUTION_TIME, no_bucket, ERROR, [with estimated cost 3 + list.length, degree = 1,{list.length},Modeled call to Collections.shuffle]