[cost][inferbo] Add models for NSAttributedString

Summary: Per title.

Reviewed By: skcho

Differential Revision: D28183310

fbshipit-source-id: 4935e1b55
master
Ezgi Çiçek 4 years ago committed by Facebook GitHub Bot
parent 186b10e4f5
commit 965d916e57

@ -355,6 +355,10 @@ module ObjectiveC = struct
Str.string_match regex procname 0
| None ->
false
let implements_ns_string_variants tenv procname =
implements "NSString" tenv procname || implements "NSAttributedString" tenv procname
end
let get_vararg_type_names tenv (call_node : Procdesc.Node.t) (ivar : Pvar.t) : string list =

@ -202,6 +202,9 @@ module ObjectiveC : sig
val implements : string -> Tenv.t -> string -> bool
(** Check whether class implements a given ObjC class *)
val implements_ns_string_variants : Tenv.t -> string -> bool
(** Check whether class implements NSString or NSAttributedString *)
val conforms_to : protocol:string -> Tenv.t -> string -> bool
(** Check whether class conforms to a given ObjC protocol *)

@ -1552,8 +1552,8 @@ let objc_malloc exp =
| Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements_collection tenv (Typ.to_string typ)
->
NSCollection.new_collection.exec model ~ret mem
| Exp.Sizeof {typ} when PatternMatch.ObjectiveC.implements "NSString" tenv (Typ.to_string typ)
->
| Exp.Sizeof {typ}
when PatternMatch.ObjectiveC.implements_ns_string_variants 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
@ -1778,9 +1778,10 @@ module Call = struct
&:: "reverseObjectEnumerator" <>$ capt_exp $--> NSCollection.iterator
; +PatternMatch.ObjectiveC.implements "NSNumber" &:: "numberWithInt:" <>$ capt_exp $--> id
; +PatternMatch.ObjectiveC.implements "NSNumber" &:: "integerValue" <>$ capt_exp $--> id
; +PatternMatch.ObjectiveC.implements "NSAttributedString" &:: "string" <>$ capt_exp $!--> id
; +PatternMatch.ObjectiveC.implements "NSString"
&:: "stringWithUTF8String:" <>$ capt_exp $!--> NSString.create_with_c_string
; +PatternMatch.ObjectiveC.implements "NSString"
; +PatternMatch.ObjectiveC.implements_ns_string_variants
&:: "length" <>$ capt_exp $--> NSString.length
; +PatternMatch.ObjectiveC.implements "NSString"
&:: "stringByAppendingString:" <>$ capt_exp $+ capt_exp $!--> NSString.concat
@ -1790,7 +1791,10 @@ module Call = struct
&:: "appendString:" <>$ capt_exp $+ capt_exp $--> NSString.append_string
; +PatternMatch.ObjectiveC.implements "NSString"
&:: "componentsSeparatedByString:" <>$ capt_exp $+ any_arg $--> NSString.split
; +PatternMatch.ObjectiveC.implements "NSString"
; +PatternMatch.ObjectiveC.implements "NSAttributedString"
&:: "initWithString:attributes:" <>$ capt_exp $+ capt_exp $+ any_arg
$--> NSString.init_with_string
; +PatternMatch.ObjectiveC.implements_ns_string_variants
&:: "initWithString:" <>$ capt_exp $+ capt_exp $--> NSString.init_with_string
; +PatternMatch.ObjectiveC.implements "NSString"
&:: "initWithBytes:length:encoding:" <>$ capt_exp $+ capt_exp $+ capt_exp $+ any_arg

@ -160,6 +160,32 @@ module NSString = struct
let substring_from_index = JavaString.substring_no_end
end
module NSAttributedString = struct
let enumerate_using_block args ({get_summary; model_env} as cost_model_env) ~ret inferbo_mem =
let pname = model_env.pname in
match List.rev args with
| _attr :: _inRange :: _options :: _usingBlock :: {exp= str} :: _captured_args -> (
let length =
BoundsOfCString.linear_length
~of_function:(Procname.to_simplified_string pname)
str cost_model_env ~ret inferbo_mem
in
match pname with
| WithBlockParameters (_, [block_name]) -> (
match get_summary (Procname.Block block_name) with
| Some {CostDomain.post= callee_summary} ->
let {BasicCostWithReason.cost= callee_cost} =
CostDomain.get_cost_kind OperationCost callee_summary
in
BasicCost.mult_loop ~iter:length ~body:callee_cost
| None ->
length )
| _ ->
length )
| _ ->
BasicCost.one ()
end
module NSCollection = struct
let get_length str ~of_function {model_env= {location}} ~ret:_ mem =
let itv =
@ -284,6 +310,9 @@ module Call = struct
$--> BoundsOfNSCollection.linear_length ~of_function:"NSArray.addObjectsFromArray:"
; +PatternMatch.ObjectiveC.implements_collection
&:: "enumerateObjectsUsingBlock:" &::.*++> NSCollection.enumerate_using_block
; +PatternMatch.ObjectiveC.implements "NSAttributedString"
&:: "enumerateAttribute:inRange:options:usingBlock:"
&::.*++> NSAttributedString.enumerate_using_block
; +PatternMatch.Java.implements_collections
&:: "sort" $ capt_exp
$+...$--> BoundsOfCollection.n_log_n_length ~of_function:"Collections.sort"

@ -124,6 +124,51 @@ bool string_has_prefix_linear(NSString* str, NSString* prefix) {
return [str hasPrefix:prefix];
}
void attributedstring_length_linear(NSAttributedString* s) {
for (int i = 0; i < s.length; i++) {
}
}
void call_string_length_linear(NSAttributedString* s) {
string_length_linear(s.string);
}
void enumerateAttribute_quadratic(NSAttributedString* attributedString,
NSString* kCTFontAttributeName,
int x) {
[attributedString
enumerateAttribute:kCTFontAttributeName
inRange:NSMakeRange(0, [attributedString length])
options:
NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:^(id value, NSRange range, BOOL* stop) {
for (int i = 0; i <= x; i++) {
}
}];
}
void enumerateAttribute_linear(NSAttributedString* attributedString,
NSString* kCTFontAttributeName,
int x) {
[attributedString
enumerateAttribute:kCTFontAttributeName
inRange:NSMakeRange(0, [attributedString length])
options:
NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:^(id value, NSRange range, BOOL* stop) {
int p = 0;
}];
}
// FN because captured block variable is added as last argument which our model
// cannot recognize
void enumerateAttribute_via_block_captured_linear_FN(NSArray* array, int x) {
__block BOOL answer = NO;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL* stop) {
answer = YES;
}];
}
@interface DummyClass : NSObject
@end

@ -1,6 +1,9 @@
${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSArray.h, NSArray.enumerateObjectsUsingBlock:[objc_blockMyBlock.call_enumerate_via_block_param_quadratic::_3], 0, OnUIThread:false, []
${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSArray.h, NSArray.enumerateObjectsUsingBlock:[objc_blockenumerateAttribute_via_block_captured_linear_FN_3], 0, OnUIThread:false, []
${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSArray.h, NSArray.enumerateObjectsUsingBlock:[objc_blockenumerate_via_block_linear_2], 0, OnUIThread:false, []
${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSArray.h, NSArray.indexOfObject:inSortedRange:options:usingComparator:[objc_blocknsarray_binary_search_log_FN_1], 0, OnUIThread:false, []
${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSAttributedString.h, NSAttributedString.enumerateAttribute:inRange:options:usingBlock:[objc_blockenumerateAttribute_linear_2], 0, OnUIThread:false, []
${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSAttributedString.h, NSAttributedString.enumerateAttribute:inRange:options:usingBlock:[objc_blockenumerateAttribute_quadratic_1], 0, OnUIThread:false, []
codetoanalyze/objc/performance/MyEnumerator.m, MyEnumerator.dealloc, 0, OnUIThread:false, []
codetoanalyze/objc/performance/MyEnumerator.m, MyEnumerator.nextObject, 5 + 3 ⋅ self->n.ub + 3 ⋅ (1+max(0, self->n.ub)), OnUIThread:false, [{1+max(0, self->n.ub)},Loop,{self->n.ub},Loop]
codetoanalyze/objc/performance/NSArray.m, MyBlock.call_enumerate_via_block_param_quadratic::, 4 + 3 ⋅ size × x->elements.length.ub + 2 ⋅ x->elements.length.ub + 2 ⋅ x->elements.length.ub × (1+max(0, size)), OnUIThread:false, [{1+max(0, size)},Loop,{x->elements.length.ub},Modeled call to enumerateObjectsUsingBlock:,{x->elements.length.ub},Modeled call to enumerateObjectsUsingBlock:,{size},Loop]
@ -96,15 +99,23 @@ codetoanalyze/objc/performance/NSSet.m, nsset_iterate_linear, 5 + 8 ⋅ (set->el
codetoanalyze/objc/performance/NSSet.m, nsset_next_object_linear, 4 + 5 ⋅ (set->elements.length.ub + 1), OnUIThread:false, [{set->elements.length.ub + 1},Loop]
codetoanalyze/objc/performance/NSString.m, DummyClass.call_string_by_appending_string_constant, 7, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, DummyClass.dealloc, 0, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, attributedstring_length_linear, 2 + 3 ⋅ s.length.ub + 3 ⋅ (s.length.ub + 1), OnUIThread:false, [{s.length.ub + 1},Loop,{s.length.ub},Loop]
codetoanalyze/objc/performance/NSString.m, call_component_separated_by_char_constant, 44, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, call_init_with_string_constant, 13, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, call_string_length_linear, 4 + 3 ⋅ s.length.ub + 4 ⋅ (s.length.ub + 1), OnUIThread:false, [{s.length.ub + 1},Call to string_length_linear,Loop,{s.length.ub},Call to string_length_linear,Loop]
codetoanalyze/objc/performance/NSString.m, component_seperated_by_char_linear, 5 + 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, 5 + 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, enumerateAttribute_linear, 5 + attributedString->strlen.ub, OnUIThread:false, [{attributedString->strlen.ub},Modeled call to enumerateAttribute:inRange:options:usingBlock:]
codetoanalyze/objc/performance/NSString.m, enumerateAttribute_quadratic, 6 + 2 ⋅ attributedString->strlen.ub + 3 ⋅ attributedString->strlen.ub × (x + 1) + 2 ⋅ attributedString->strlen.ub × (2+max(-1, x)), OnUIThread:false, [{2+max(-1, x)},Loop,{x + 1},Loop,{attributedString->strlen.ub},Modeled call to enumerateAttribute:inRange:options:usingBlock:]
codetoanalyze/objc/performance/NSString.m, enumerateAttribute_via_block_captured_linear_FN, 3, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, has_prefix_constant, 10, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, init_string_constant, 8, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, init_with_bytes_linear, 8 + 3 ⋅ length + 3 ⋅ (length + 1), OnUIThread:false, [{length + 1},Loop,{length},Loop]
codetoanalyze/objc/performance/NSString.m, init_with_string_constant, 38, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, init_with_string_linear, 6 + 3 ⋅ s.length.ub + 3 ⋅ (s.length.ub + 1), OnUIThread:false, [{s.length.ub + 1},Loop,{s.length.ub},Loop]
codetoanalyze/objc/performance/NSString.m, objc_blockenumerateAttribute_linear_2, 1, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, objc_blockenumerateAttribute_quadratic_1, 2 + 3 ⋅ (x + 1) + 2 ⋅ (2+max(-1, x)), OnUIThread:false, [{2+max(-1, x)},Loop,{x + 1},Loop]
codetoanalyze/objc/performance/NSString.m, objc_blockenumerateAttribute_via_block_captured_linear_FN_3, 2, OnUIThread:false, []
codetoanalyze/objc/performance/NSString.m, rangeof_character_from_set_linear, 4 + m.length.ub, OnUIThread:false, [{m.length.ub},Modeled call to NSString.rangeOfString:]
codetoanalyze/objc/performance/NSString.m, rangeof_string_quadratic, 4 + n.length.ub × m.length.ub, OnUIThread:false, [{m.length.ub},Modeled call to NSString.rangeOfString:,{n.length.ub},Modeled call to NSString.rangeOfString:]
codetoanalyze/objc/performance/NSString.m, replace_linear_FP, , OnUIThread:false, [Unbounded loop,Loop]

Loading…
Cancel
Save