diff --git a/infer/src/pulse/PulseModels.ml b/infer/src/pulse/PulseModels.ml index 686586e6c..864eb68e8 100644 --- a/infer/src/pulse/PulseModels.ml +++ b/infer/src/pulse/PulseModels.ml @@ -1798,6 +1798,12 @@ module ProcNameDispatcher = struct ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSDictionary") &:: "sharedKeySetForKeys:" <>$ capt_arg_payload $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSDictionary.sharedKeySetForKeys" + ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSSet") + &:: "setWithObject:" <>$ capt_arg_payload + $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSSet.setWithObject" + ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSSet") + &:: "setByAddingObject:" <>$ any_arg $+ capt_arg_payload + $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSSet.setByAddingObject" ; +match_regexp_opt Config.pulse_model_return_nonnull &::.*--> Misc.return_positive ~desc:"modelled as returning not null due to configuration option" diff --git a/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm b/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm index 41b3b3658..74856339d 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm +++ b/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm @@ -389,3 +389,40 @@ void dictionaryWithSharedKeySetForKeysOk() { void dictionaryWithSharedKeySetForKeysBad() { dictionaryWithSharedKeySetForKeys(nil); } + +void setWithObject(id object) { NSSet* set = [NSSet setWithObject:object]; } + +void setWithObjectOk() { setWithObject(@"obj"); } + +void setWithObjectBad() { setWithObject(nil); } + +void setByAddingObject(id object) { + NSSet* set = [NSSet set]; + set = [set setByAddingObject:object]; +} + +void setByAddingObjectOk() { setByAddingObject(@"obj"); } + +void setByAddingObjectBad() { setByAddingObject(nil); } + +void setWithObjectsForCount(id object) { + NSString* values[1]; + values[0] = object; + + NSSet* set = [NSSet setWithObjects:values count:1]; +} + +void setWithObjectsForCountOk() { setWithObjectsForCount(@"obj"); } + +void FN_setWithObjectsForCountBad() { setWithObjectsForCount(nil); } + +void setInitWithObjectsForCount(id object) { + NSString* values[1]; + values[0] = object; + + NSSet* set = [[NSSet alloc] initWithObjects:values count:1]; +} + +void setInitWithObjectsForCountOk() { setInitWithObjectsForCount(@"obj"); } + +void FN_setInitWithObjectsForCountBad() { setInitWithObjectsForCount(nil); } diff --git a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp index 6fcacb602..b86987b3c 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp @@ -19,6 +19,8 @@ codetoanalyze/objcpp/pulse/NPEBasic.mm, removeObjectsAtIndexesFromArrayBad, 1, N codetoanalyze/objcpp/pulse/NPEBasic.mm, replaceNilInArrayBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,in call to `NSMutableArray.replaceObjectAtIndex:withObject:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, replaceObjectsAtIndexesWithNilObjectsInArrayBad, 2, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `replaceObjectsAtIndexesWithObjectsInArray` here,parameter `objects` of replaceObjectsAtIndexesWithObjectsInArray,in call to `NSMutableArray.replaceObjectsAtIndexes:withObjects:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, replaceObjectsAtNilIndexesWithObjectsInArrayBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `replaceObjectsAtIndexesWithObjectsInArray` here,parameter `indexset` of replaceObjectsAtIndexesWithObjectsInArray,in call to `NSMutableArray.replaceObjectsAtIndexes:withObjects:` (modelled),invalid access occurs here] +codetoanalyze/objcpp/pulse/NPEBasic.mm, setByAddingObjectBad, 0, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `setByAddingObject` here,parameter `object` of setByAddingObject,in call to `NSSet.setByAddingObject` (modelled),invalid access occurs here] +codetoanalyze/objcpp/pulse/NPEBasic.mm, setWithObjectBad, 0, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `setWithObject` here,parameter `object` of setWithObject,in call to `NSSet.setWithObject` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testAccessPropertyAccessorBad, 2, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [is the null pointer,assigned,when calling `SomeObject.ptr` here,parameter `self` of SomeObject.ptr,invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODBad, 2, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [is the null pointer,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODLatent, 7, NIL_MESSAGING_TO_NON_POD, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here]