diff --git a/infer/src/bufferoverrun/bufferOverrunModels.ml b/infer/src/bufferoverrun/bufferOverrunModels.ml index 3e6fd38a4..e04553550 100644 --- a/infer/src/bufferoverrun/bufferOverrunModels.ml +++ b/infer/src/bufferoverrun/bufferOverrunModels.ml @@ -1903,6 +1903,7 @@ module Call = struct &:: "singletonMap" <>--> Collection.singleton_collection ; +PatternMatch.Java.implements_collections &::+ unmodifiable <>$ capt_exp $--> Collection.iterator + ; +PatternMatch.Java.implements_set &:: "of" &++> Collection.of_list ; +PatternMatch.Java.implements_google "common.collect.ImmutableSet" &:: "of" &++> Collection.of_list ; +PatternMatch.Java.implements_google "common.base.Preconditions" diff --git a/infer/src/cost/costModels.ml b/infer/src/cost/costModels.ml index 4855a0362..563c66a14 100644 --- a/infer/src/cost/costModels.ml +++ b/infer/src/cost/costModels.ml @@ -274,6 +274,13 @@ module Call = struct ; +PatternMatch.Java.implements_arrays &:: "sort" $ capt_exp $+...$--> BoundsOfArray.n_log_n_length ~of_function:"Arrays.sort" + ; +PatternMatch.Java.implements_set &:: "contains" <>$ any_arg $+ any_arg + $--> unit_cost_model + ; +PatternMatch.Java.implements_set &:: "containsAll" <>$ any_arg $+ capt_exp + $--> BoundsOfCollection.linear_length ~of_function:"Set.containsAll" + ; +PatternMatch.Java.implements_collection + &:: "removeAll" <>$ any_arg $+ capt_exp + $--> BoundsOfCollection.linear_length ~of_function:"Collection.removeAll" ; +PatternMatch.Java.implements_list &:: "contains" <>$ capt_exp $+...$--> BoundsOfCollection.linear_length ~of_function:"List.contains" diff --git a/infer/tests/codetoanalyze/java/performance/SetTest.java b/infer/tests/codetoanalyze/java/performance/SetTest.java new file mode 100644 index 000000000..941a263fc --- /dev/null +++ b/infer/tests/codetoanalyze/java/performance/SetTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +class SetTest { + + // // Set.of creates an immutable set + // private static final Set StaticSet = Set.of("a"); + + void contains_empty_constant(HashSet set) { + set.contains(""); + } + + void containsAll_linear(Set set, ArrayList list) { + set.containsAll(list); + } + + void removeAll_linear(HashSet set, ArrayList list) { + set.removeAll(list); + } + + // void loop_of_constant() { + // Set my_set = Set.of("a", "b", "c", "d", "e", "f", "g"); + // for (String el : my_set) {} + // } + + // // here, we cannot yet recognize that StaticSet is an immutable set + // // created by Set.of operation in the class initializer. + // void immutable_set_of_constant_FP() { + // for (int i = 0; i <= StaticSet.size(); i++) {} + // } +} diff --git a/infer/tests/codetoanalyze/java/performance/cost-issues.exp b/infer/tests/codetoanalyze/java/performance/cost-issues.exp index fb2708bc4..ae912d27a 100644 --- a/infer/tests/codetoanalyze/java/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/java/performance/cost-issues.exp @@ -322,6 +322,10 @@ codetoanalyze/java/performance/PreconditionTest.java, PreconditionTest.checkArgu codetoanalyze/java/performance/PreconditionTest.java, PreconditionTest.checkNotNull_linear(java.util.ArrayList,java.lang.Object):void, 12 + 8 ⋅ list.length + 3 ⋅ (list.length + 1), OnUIThread:false, [{list.length + 1},Loop,{list.length},Loop] codetoanalyze/java/performance/PreconditionTest.java, PreconditionTest.checkState_constant(java.util.ArrayList):void, 23, OnUIThread:false, [] codetoanalyze/java/performance/PreconditionTest.java, PreconditionTest.constant_array(int[]):void, 36, OnUIThread:false, [] +codetoanalyze/java/performance/SetTest.java, SetTest.(), 2, OnUIThread:false, [] +codetoanalyze/java/performance/SetTest.java, SetTest.containsAll_linear(java.util.Set,java.util.ArrayList):void, 3 + list.length, OnUIThread:false, [{list.length},Modeled call to Set.containsAll] +codetoanalyze/java/performance/SetTest.java, SetTest.contains_empty_constant(java.util.HashSet):void, 3, OnUIThread:false, [] +codetoanalyze/java/performance/SetTest.java, SetTest.removeAll_linear(java.util.HashSet,java.util.ArrayList):void, 3 + list.length, OnUIThread:false, [{list.length},Modeled call to Collection.removeAll] codetoanalyze/java/performance/StringBuilderTest.java, StringBuilderTest.(), 2, OnUIThread:false, [] codetoanalyze/java/performance/StringBuilderTest.java, StringBuilderTest.append_linear(java.lang.String):void, 23 + 5 ⋅ (s.length + 2) + 3 ⋅ (s.length + 3), OnUIThread:false, [{s.length + 3},Call to void StringBuilderTest.new_linear(String),Loop,{s.length + 2},Call to void StringBuilderTest.new_linear(String),Loop] codetoanalyze/java/performance/StringBuilderTest.java, StringBuilderTest.new_capacity_constant():void, 22, OnUIThread:false, []