diff --git a/infer/tests/codetoanalyze/objc/performance/NSArray.m b/infer/tests/codetoanalyze/objc/performance/NSArray.m new file mode 100644 index 000000000..71f3ac9eb --- /dev/null +++ b/infer/tests/codetoanalyze/objc/performance/NSArray.m @@ -0,0 +1,131 @@ +/* + * 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 + +// init array + +void nsarray_init_constant_FP() { + NSArray* array = [[NSArray alloc] init]; + + for (int i = 0; i < array.count; i++) { + } +} + +void nsarray_init_with_array_linear_FP(NSArray* array) { + NSArray* ref_array = [[NSArray alloc] initWithArray:array]; + + for (int i = 0; i < ref_array.count; i++) { + } +} + +void nsarray_init_with_array_constant_FP() { + NSArray* array = [[NSArray alloc] init]; + nsarray_init_with_array_linear_FP(array); +} + +void nsarray_init_with_array_copy_linear_FP(NSArray* array) { + NSArray* copy_array = [[NSArray alloc] initWithArray:array copyItems:YES]; + for (int i = 0; i < copy_array.count; i++) { + } +} + +NSArray* nsarray_init_with_objects_constant() { + NSString* strings[3]; + strings[0] = @"First"; + strings[1] = @"Second"; + strings[2] = @"Third"; + + return [NSArray arrayWithObjects:strings count:2]; +} + +// derive new array + +NSArray* nsarray_add_object_constant(id obj) { + NSArray* array = [[NSArray alloc] init]; + return [array arrayByAddingObject:obj]; +} + +NSArray* nsarray_add_objects_from_array_linear_FN(NSArray* append_array) { + NSArray* array = [[NSArray alloc] init]; + return [array arrayByAddingObjectsFromArray:append_array]; +} + +// query element + +void nsarray_access_constant() { + NSArray* array = @[ @1.0f, @2.0f, @3.0f, @4.0f, @5.0f, @6.0f, @7.0f, @8.0f ]; + for (int i = 0; i < 4; i++) { + [array objectAtIndex:i]; + } +} + +void nsarray_access_linear_FP(NSArray* array) { + id obj; + for (int i = 0; i < array.count; i++) { + obj = array[i]; + } +} + +void nsarray_contains_object_linear_FN(NSArray* array) { + [array containsObject:@1]; +} + +id nsarray_first_object_constant(NSArray* array) { return array.firstObject; } + +id nsarray_last_object_constant(NSArray* array) { return array.lastObject; } + +// find element +NSInteger nsarray_binary_search_log_FN(NSArray* sorted_array) { + NSNumber* target = @5; + return [sorted_array indexOfObject:target + inSortedRange:NSMakeRange(0, sorted_array.count) + options:NSBinarySearchingFirstEqual + usingComparator:^(id lhs, id rhs) { + return [lhs compare:rhs]; + }]; +} + +// sort array + +NSArray* nsarray_sort_using_descriptors_constant() { + NSArray* array = @[ @"Grapes", @"Apples", @"Oranges" ]; + NSSortDescriptor* sd = [[NSSortDescriptor alloc] initWithKey:nil + ascending:YES]; + return [array sortedArrayUsingDescriptors:@[ sd ]]; +} + +NSArray* nsarray_sort_using_descriptors_nlogn_FN(NSArray* array) { + NSSortDescriptor* sd = [[NSSortDescriptor alloc] initWithKey:nil + ascending:YES]; + return [array sortedArrayUsingDescriptors:@[ sd ]]; +} + +// iterate through array + +void nsarray_iterate_linear_FN(NSArray* array) { + NSInteger sum = 0; + for (id obj in array) { + sum += (NSInteger)obj; + } +} + +void nsarray_enumerator_linear_FN(NSArray* array) { + NSEnumerator* enumerator = [array objectEnumerator]; + + id obj; + NSInteger sum = 0; + + while (obj = [enumerator nextObject]) { + sum += (NSInteger)obj; + } +} + +// compare array +boolean_t nsarray_is_equal_to_array_linear_FN(NSArray* array1, + NSArray* array2) { + return [array1 isEqualToArray:array2]; +} diff --git a/infer/tests/codetoanalyze/objc/performance/NSMutableArray.m b/infer/tests/codetoanalyze/objc/performance/NSMutableArray.m new file mode 100644 index 000000000..00a885350 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/performance/NSMutableArray.m @@ -0,0 +1,124 @@ +/* + * 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 + +// init array + +void nsmarray_init_with_capacity_constant_FP() { + NSMutableArray* table = [[NSMutableArray alloc] initWithCapacity:256]; + + for (int i = 0; i < table.count; i++) { + table[i] = @"somevalue"; + } +} + +// add element + +void nsmarray_empty_ok_costant() { + NSMutableArray* array = [[NSMutableArray alloc] init]; + [array insertObject:@1 atIndex:0]; +} + +void nsmarray_add_in_loop_constant_FP() { + NSMutableArray* array = [[NSMutableArray alloc] init]; + for (int i = 0; i < 10; i++) { + [array addObject:[NSNumber numberWithInt:i]]; + } + for (int i = 0; i < array.count; i++) { + } +} + +void nsmarray_add_in_loop_linear(NSUInteger n) { + NSMutableArray* array = [[NSMutableArray alloc] init]; + for (int i = 0; i < n; i++) { + [array addObject:[NSNumber numberWithInt:i]]; + } + for (int i = 0; i < n; i++) { + } +} + +void nsmarray_add_in_loop_quadratic(NSUInteger n, NSUInteger m) { + NSMutableArray* array = [[NSMutableArray alloc] init]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + [array addObject:[NSNumber numberWithInt:i + j]]; + } + } +} + +void nsmarray_add_then_loop_constant_FP() { + NSMutableArray* array = [[NSMutableArray alloc] init]; + [array addObject:@0]; + [array addObject:@1]; + [array addObject:@2]; + [array addObject:@3]; + [array addObject:@4]; + [array addObject:@5]; + [array addObject:@6]; + [array addObject:@7]; + [array addObject:@8]; + [array addObject:@9]; + [array addObject:@10]; + + for (int i = 0; i < array.count; i++) { + } +} + +void nsmarray_add_all_constant() { + NSMutableArray* array1 = [[NSMutableArray alloc] init]; + [array1 addObject:@2]; + [array1 addObject:@3]; + + NSMutableArray* array2 = [[NSMutableArray alloc] init]; + [array2 addObject:@0]; + [array2 addObject:@1]; + + NSIndexSet* index_set = [[NSIndexSet alloc] initWithIndex:0]; + + [array2 addObjectsFromArray:array1]; +} + +// set element + +void nsmarray_set_constant(NSMutableArray* array) { array[0] = @1; } + +void nsmarray_set_linear_FP(NSMutableArray* array) { + for (int i = 0; i < array.count; i++) { + array[i] = [NSNumber numberWithInt:([array[i] intValue] + 1)]; + } +} + +void nsmarray_set_constant_FP() { + NSMutableArray* array = [[NSMutableArray alloc] init]; + [array addObject:@0]; + [array addObject:@1]; + [array addObject:@2]; + + for (int i = 0; i < array.count; i++) { + array[i] = [NSNumber numberWithInt:i]; + } +} + +// remove element + +id nsmarray_reomove_constant() { + NSMutableArray* array = [[NSMutableArray alloc] init]; + [array addObject:@0]; + [array addObject:@1]; + [array removeObjectAtIndex:0]; + return array[0]; +} + +void nsmarray_remove_in_loop_constant_FP() { + NSMutableArray* array = [[NSMutableArray alloc] init]; + for (int i = 0; i < 10; i++) { + [array addObject:[NSNumber numberWithInt:i]]; + } + for (int i = 0; i < array.count; i++) { + [array removeObjectAtIndex:i]; + } +} diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index 41bd01b57..b208ed963 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -1,4 +1,35 @@ +codetoanalyze/objc/performance/NSArray.m, nsarray_access_constant, 42, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_access_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 68, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_add_object_constant, 8, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_add_objects_from_array_linear_FN, 8, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_binary_search_log_FN, 10, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_contains_object_linear_FN, 4, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_enumerator_linear_FN, 14, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_first_object_constant, 4, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 14, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_constant_FP, ⊤, OnUIThread:false, [Call to nsarray_init_with_array_linear_FP,Unbounded loop,Loop at line 21, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_copy_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 32, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 21, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_objects_constant, 9, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_is_equal_to_array_linear_FN, 5, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_iterate_linear_FN, 14, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_last_object_constant, 4, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_constant, 14, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, nsarray_sort_using_descriptors_nlogn_FN, 9, OnUIThread:false, [] +codetoanalyze/objc/performance/NSArray.m, objc_blocknsarray_binary_search_log_FN_1, 5, OnUIThread:false, [] codetoanalyze/objc/performance/NSInteger.m, nsinteger_value_linear, 3 + 3 ⋅ integer + 2 ⋅ (1+max(0, integer)), OnUIThread:false, [{1+max(0, integer)},Loop at line 10, column 3,{integer},Loop at line 10, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_all_constant, 25, OnUIThread:false, [] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_in_loop_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 31, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_in_loop_linear, 8 + 7 ⋅ n + 3 ⋅ n + 2 ⋅ (n + 1) + 2 ⋅ (n + 1), OnUIThread:false, [{n + 1},Loop at line 40, column 3,{n + 1},Loop at line 37, column 3,{n},Loop at line 40, column 3,{n},Loop at line 37, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_in_loop_quadratic, 6 + 5 ⋅ n + 8 ⋅ n × m + 2 ⋅ n × (m + 1) + 2 ⋅ (n + 1), OnUIThread:false, [{n + 1},Loop at line 46, column 3,{m + 1},Loop at line 47, column 5,{m},Loop at line 47, column 5,{n},Loop at line 46, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_then_loop_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 67, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_empty_ok_costant, 7, OnUIThread:false, [] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_init_with_capacity_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 14, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_in_loop_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 121, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_reomove_constant, 15, OnUIThread:false, [] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_constant, 4, OnUIThread:false, [] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 101, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 90, column 3] codetoanalyze/objc/performance/NSString.m, call_component_separated_by_string_constant_FP, ⊤, OnUIThread:false, [Call to component_seperated_by_string_linear_FP,Unbounded loop,Loop at line 42, column 3] codetoanalyze/objc/performance/NSString.m, call_init_with_string_constant_FP, ⊤, OnUIThread:false, [Call to init_with_string_linear_FP,Unbounded loop,Loop at line 70, column 3] codetoanalyze/objc/performance/NSString.m, component_seperated_by_string_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop at line 42, column 3] diff --git a/infer/tests/codetoanalyze/objc/performance/issues.exp b/infer/tests/codetoanalyze/objc/performance/issues.exp index 100e99491..b565812a4 100644 --- a/infer/tests/codetoanalyze/objc/performance/issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/issues.exp @@ -1,3 +1,26 @@ +codetoanalyze/objc/performance/NSArray.m, nsarray_access_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 68, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_access_linear_FP, 2, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSArray.m, nsarray_enumerator_linear_FN, 7, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Assignment,,Unknown value from: NSEnumerator.nextObject,Assignment,Binary operation: ([-oo, +oo] + [-oo, +oo]):signed64] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 14, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_constant_FP, 3, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to nsarray_init_with_array_linear_FP,Unbounded loop,Loop at line 21, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_copy_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 32, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_copy_linear_FP, 2, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 21, column 3] +codetoanalyze/objc/performance/NSArray.m, nsarray_init_with_array_linear_FP, 3, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSArray.m, nsarray_iterate_linear_FN, 3, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Assignment,,Unknown value from: NSArray.nextObject,Assignment,Binary operation: ([-oo, +oo] + [-oo, +oo]):signed64] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_in_loop_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 31, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_in_loop_constant_FP, 5, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_then_loop_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 67, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_add_then_loop_constant_FP, 14, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_init_with_capacity_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 14, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_init_with_capacity_constant_FP, 3, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_in_loop_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 121, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_in_loop_constant_FP, 5, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 101, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_constant_FP, 6, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSArray.count,Binary operation: ([0, +oo] + 1):signed32] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 90, column 3] +codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_linear_FP, 2, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSNumber.intValue,Binary operation: ([-oo, +oo] + 1):signed32] codetoanalyze/objc/performance/NSString.m, call_component_separated_by_string_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to component_seperated_by_string_linear_FP,Unbounded loop,Loop at line 42, column 3] codetoanalyze/objc/performance/NSString.m, call_init_with_string_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Call to init_with_string_linear_FP,Unbounded loop,Loop at line 70, column 3] codetoanalyze/objc/performance/NSString.m, component_seperated_by_string_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop at line 42, column 3]