diff --git a/infer/src/cost/costModels.ml b/infer/src/cost/costModels.ml index f269621af..8c4b17224 100644 --- a/infer/src/cost/costModels.ml +++ b/infer/src/cost/costModels.ml @@ -137,6 +137,7 @@ module JavaString = struct end module BoundsOfCollection = BoundsOf (CostUtils.Collection) +module BoundsOfNSCollection = BoundsOf (CostUtils.NSCollection) module BoundsOfArray = BoundsOf (CostUtils.Array) module BoundsOfCString = BoundsOf (CostUtils.CString) @@ -214,17 +215,26 @@ module Call = struct &:: "componentsSeparatedByString:" <>$ capt_exp $+ capt_exp $--> NSString.op_on_two_str BasicCost.mult ~of_function:"NSString.componentsSeparatedByString:" - ; -"NSArray" &:: "initWithArray:" <>$ any_arg $+ capt_exp - $--> NSCollection.get_length ~of_function:"NSArray.initWithArray:" - ; -"NSArray" &:: "isEqualToArray:" <>$ capt_exp $+ capt_exp + ; +PatternMatch.ObjectiveC.implements "NSArray" + &:: "initWithArray:" <>$ any_arg $+ capt_exp + $--> BoundsOfNSCollection.linear_length ~of_function:"NSArray.initWithArray:" + ; +PatternMatch.ObjectiveC.implements "NSArray" + &:: "isEqualToArray:" <>$ capt_exp $+ capt_exp $--> NSCollection.op_on_two_coll BasicCost.min_default_left ~of_function:"NSArray.isEqualToArray:" - ; -"NSArray" &:: "containsObject:" <>$ capt_exp $+ any_arg - $--> NSCollection.get_length ~of_function:"NSArray.containsObject:" - ; -"NSMutableArray" &:: "removeAllObjects" <>$ capt_exp - $--> NSCollection.get_length ~of_function:"NSArray.removeAllObjects" - ; -"NSMutableArray" &:: "addObjectsFromArray:" <>$ any_arg $+ capt_exp - $--> NSCollection.get_length ~of_function:"NSArray.addObjectsFromArray:" + ; +PatternMatch.ObjectiveC.implements "NSArray" + &:: "containsObject:" <>$ capt_exp $+ any_arg + $--> BoundsOfNSCollection.linear_length ~of_function:"NSArray.containsObject:" + ; +PatternMatch.ObjectiveC.implements "NSArray" + &:: "sortedArrayUsingDescriptors:" <>$ capt_exp $+ any_arg + $--> BoundsOfNSCollection.n_log_n_length + ~of_function:"NSArray.sortedArrayUsingDescriptors:" + ; +PatternMatch.ObjectiveC.implements "NSMutableArray" + &:: "removeAllObjects" <>$ capt_exp + $--> BoundsOfNSCollection.linear_length ~of_function:"NSArray.removeAllObjects" + ; +PatternMatch.ObjectiveC.implements "NSMutableArray" + &:: "addObjectsFromArray:" <>$ any_arg $+ capt_exp + $--> BoundsOfNSCollection.linear_length ~of_function:"NSArray.addObjectsFromArray:" ; +PatternMatch.Java.implements_collections &:: "sort" $ capt_exp $+...$--> BoundsOfCollection.n_log_n_length ~of_function:"Collections.sort" diff --git a/infer/src/cost/costUtils.ml b/infer/src/cost/costUtils.ml index 3603349d8..9e1e91882 100644 --- a/infer/src/cost/costUtils.ml +++ b/infer/src/cost/costUtils.ml @@ -55,6 +55,11 @@ module Collection : S = struct BufferOverrunModels.Collection.eval_collection_length coll_exp inferbo_mem end +module NSCollection : S = struct + let length coll_exp inferbo_mem = + BufferOverrunModels.NSCollection.eval_collection_length coll_exp inferbo_mem +end + module CString : S = struct let length exp inferbo_mem = BufferOverrunSemantics.eval_string_len exp inferbo_mem end diff --git a/infer/tests/codetoanalyze/objc/performance/NSArray.m b/infer/tests/codetoanalyze/objc/performance/NSArray.m index 64cb16a42..496c95372 100644 --- a/infer/tests/codetoanalyze/objc/performance/NSArray.m +++ b/infer/tests/codetoanalyze/objc/performance/NSArray.m @@ -137,7 +137,7 @@ NSArray* nsarray_sort_using_descriptors_constant() { return [array sortedArrayUsingDescriptors:@[ sd ]]; } -NSArray* nsarray_sort_using_descriptors_nlogn_FN(NSArray* array) { +NSArray* nsarray_sort_using_descriptors_nlogn(NSArray* array) { NSSortDescriptor* sd = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES]; return [array sortedArrayUsingDescriptors:@[ sd ]]; diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index e7ae9a9f3..973c5063a 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -22,8 +22,8 @@ codetoanalyze/objc/performance/NSArray.m, nsarray_last_object_constant, 4, OnUI codetoanalyze/objc/performance/NSArray.m, nsarray_next_object_constant, 25, OnUIThread:false, [] codetoanalyze/objc/performance/NSArray.m, nsarray_next_object_linear, 5 + array->elements.length.ub + 4 ⋅ (array->elements.length.ub + 1), OnUIThread:false, [{array->elements.length.ub + 1},Loop,{array->elements.length.ub},Loop] codetoanalyze/objc/performance/NSArray.m, nsarray_object_at_indexed_constant, 34, OnUIThread:false, [] -codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_constant, 34, OnUIThread:false, [] -codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_nlogn_FN, 10, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_constant, 39, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_nlogn, 9 + array->elements.length.ub × log(array->elements.length.ub), OnUIThread:false, [{array->elements.length.ub},Modeled call to NSArray.sortedArrayUsingDescriptors:,{array->elements.length.ub},Modeled call to NSArray.sortedArrayUsingDescriptors:] codetoanalyze/objc/performance/NSArray.m, objc_blocknsarray_binary_search_log_FN_1, 5, OnUIThread:false, [] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_keys_linear1, 3 + 3 ⋅ dict->elements.length.ub + 4 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_all_keys_linear2, 6 + 3 ⋅ dict->elements.length.ub + 3 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop]