From 3d561ca1dbda4358a8eb50d64eb488f0ca272422 Mon Sep 17 00:00:00 2001 From: Qianyi Shu Date: Tue, 4 Aug 2020 01:39:54 -0700 Subject: [PATCH] [cost] add alloc for NSObject and NSString.init as an example function using alloc Summary: Implement `alloc` and implement initialisation method that uses the return value of `alloc`, i.e. `NSString.init`. Reviewed By: ezgicicek Differential Revision: D22840080 fbshipit-source-id: 47a7523e3 --- .../src/bufferoverrun/bufferOverrunModels.ml | 34 +++++++++++-------- .../codetoanalyze/objc/performance/NSString.m | 6 ++++ .../objc/performance/cost-issues.exp | 1 + .../codetoanalyze/objc/performance/issues.exp | 1 + 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/infer/src/bufferoverrun/bufferOverrunModels.ml b/infer/src/bufferoverrun/bufferOverrunModels.ml index 4fcc9eaca..5c18c0e28 100644 --- a/infer/src/bufferoverrun/bufferOverrunModels.ml +++ b/infer/src/bufferoverrun/bufferOverrunModels.ml @@ -149,18 +149,6 @@ let malloc ~can_be_zero size_exp = {exec; check} -let objc_malloc exp = - let can_be_zero = true in - let exec ({tenv} as model) ~ret mem = - match exp with - | Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSArray" tenv (Typ.to_string typ) -> - (malloc ~can_be_zero Exp.zero).exec model ~ret mem - | _ -> - (malloc ~can_be_zero exp).exec model ~ret mem - in - {exec; check= check_alloc_size ~can_be_zero exp} - - let calloc size_exp stride_exp = let byte_size_exp = Exp.BinOp (Binop.Mult (Some Typ.size_t), size_exp, stride_exp) in malloc byte_size_exp @@ -1379,7 +1367,7 @@ end module NSString = struct let fn = JavaString.fn - let create_string_from_c_string src_exp = + let create_with_c_string src_exp = let exec model_env ~ret mem = let v = Sem.eval_string_len src_exp mem in JavaString.create_with_length model_env ~ret ~begin_idx:Exp.zero ~end_v:v mem @@ -1422,6 +1410,21 @@ module NSString = struct {exec; check= no_check} end +let objc_malloc exp = + let can_be_zero = true in + let exec ({tenv} as model) ~ret mem = + match exp with + | Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSArray" tenv (Typ.to_string typ) -> + (malloc ~can_be_zero Exp.zero).exec model ~ret mem + | Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSString" tenv (Typ.to_string typ) + -> + (NSString.create_with_c_string (Exp.Const (Const.Cstr ""))).exec model ~ret mem + | _ -> + (malloc ~can_be_zero exp).exec model ~ret mem + in + {exec; check= check_alloc_size ~can_be_zero exp} + + module Preconditions = struct let check_argument exp = let exec {integer_type_widths; location} ~ret:_ mem = @@ -1566,8 +1569,8 @@ module Call = struct ; -"CFArrayGetValueAtIndex" <>$ capt_var_exn $+ capt_exp $!--> NSCollection.get_at_index ; -"CFDictionaryGetCount" <>$ capt_exp $!--> NSCollection.length ; -"MCFArrayGetCount" <>$ capt_exp $!--> NSCollection.length - ; +PatternMatch.ObjectiveC.implements "NSArray" &:: "array" <>--> NSCollection.empty_array ; +PatternMatch.ObjectiveC.implements "NSArray" &:: "init" <>$ capt_exp $--> id + ; +PatternMatch.ObjectiveC.implements "NSArray" &:: "array" <>--> NSCollection.empty_array ; +PatternMatch.ObjectiveC.implements "NSArray" &:: "count" <>$ capt_exp $!--> NSCollection.length ; +PatternMatch.ObjectiveC.implements "NSArray" @@ -1591,8 +1594,9 @@ module Call = struct &:: "allValues" <>$ capt_exp $--> create_copy_array ; +PatternMatch.ObjectiveC.implements "NSNumber" &:: "numberWithInt:" <>$ capt_exp $--> id ; +PatternMatch.ObjectiveC.implements "NSNumber" &:: "integerValue" <>$ capt_exp $--> id + ; +PatternMatch.ObjectiveC.implements "NSString" &:: "init" <>$ capt_exp $--> id ; +PatternMatch.ObjectiveC.implements "NSString" - &:: "stringWithUTF8String:" <>$ capt_exp $!--> NSString.create_string_from_c_string + &:: "stringWithUTF8String:" <>$ capt_exp $!--> NSString.create_with_c_string ; +PatternMatch.ObjectiveC.implements "NSString" &:: "length" <>$ capt_exp $--> NSString.length ; +PatternMatch.ObjectiveC.implements "NSString" diff --git a/infer/tests/codetoanalyze/objc/performance/NSString.m b/infer/tests/codetoanalyze/objc/performance/NSString.m index 2fcfe458e..48c1ec8e6 100644 --- a/infer/tests/codetoanalyze/objc/performance/NSString.m +++ b/infer/tests/codetoanalyze/objc/performance/NSString.m @@ -63,6 +63,12 @@ void init_with_bytes_linear_FP(const void* bytes, } } +void init_string_constant() { + NSString* str = [[NSString alloc] init]; + for (int i = 0; i < str.length; i++) { + } +} + void init_with_string_constant_FP() { NSString* s = @"abcd"; NSString* str = [[NSString alloc] initWithString:s]; diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index cdaa5b25e..2a27b2658 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -56,6 +56,7 @@ codetoanalyze/objc/performance/NSString.m, call_init_with_string_constant_FP, codetoanalyze/objc/performance/NSString.m, component_seperated_by_char_linear, 6 + m.length.ub + 3 ⋅ (-1+max(2, m.length.ub)) + 3 ⋅ (max(2, m.length.ub)), OnUIThread:false, [{max(2, m.length.ub)},Loop,{-1+max(2, m.length.ub)},Loop,{m.length.ub},Modeled call to NSString.componentsSeparatedByString:] codetoanalyze/objc/performance/NSString.m, component_seperated_by_string_linear, 6 + sep.length.ub × m.length.ub + 3 ⋅ (-1+max(2, m.length.ub)) + 3 ⋅ (max(2, m.length.ub)), OnUIThread:false, [{max(2, m.length.ub)},Loop,{-1+max(2, m.length.ub)},Loop,{m.length.ub},Modeled call to NSString.componentsSeparatedByString:,{sep.length.ub},Modeled call to NSString.componentsSeparatedByString:] codetoanalyze/objc/performance/NSString.m, has_prefix_constant, 13, OnUIThread:false, [] +codetoanalyze/objc/performance/NSString.m, init_string_constant, 9, OnUIThread:false, [] codetoanalyze/objc/performance/NSString.m, init_with_bytes_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop] codetoanalyze/objc/performance/NSString.m, init_with_string_constant_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop] codetoanalyze/objc/performance/NSString.m, init_with_string_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop] diff --git a/infer/tests/codetoanalyze/objc/performance/issues.exp b/infer/tests/codetoanalyze/objc/performance/issues.exp index 261da0af9..68546e65f 100644 --- a/infer/tests/codetoanalyze/objc/performance/issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/issues.exp @@ -19,6 +19,7 @@ codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_in_loop_constan codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_in_loop_constant, 6, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, [Here] codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_set_linear, 2, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSNumber.intValue,Binary operation: ([-oo, +oo] + 1):signed32] 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] +codetoanalyze/objc/performance/NSString.m, init_string_constant, 2, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, [Here] codetoanalyze/objc/performance/NSString.m, init_with_bytes_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop] codetoanalyze/objc/performance/NSString.m, init_with_bytes_linear_FP, 6, INTEGER_OVERFLOW_U5, no_bucket, ERROR, [,Unknown value from: NSString.initWithBytes:length:encoding:,Binary operation: ([0, +oo] + 1):signed32] codetoanalyze/objc/performance/NSString.m, init_with_string_constant_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop]