diff --git a/infer/src/pulse/PulseModels.ml b/infer/src/pulse/PulseModels.ml index 5e33b6b58..177a31436 100644 --- a/infer/src/pulse/PulseModels.ml +++ b/infer/src/pulse/PulseModels.ml @@ -1771,6 +1771,12 @@ module ProcNameDispatcher = struct &:: "replaceObjectAtIndex:withObject:" <>$ any_arg $+ any_arg $+ capt_arg_payload $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSMutableArray.replaceObjectAtIndex:withObject:" + ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSMutableSet") + &:: "addObject:" <>$ any_arg $+ capt_arg_payload + $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSMutableSet.addObject:" + ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSMutableSet") + &:: "removeObject:" <>$ any_arg $+ capt_arg_payload + $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSMutableSet.removeObject:" ; +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 3d0a464fb..a38d7f812 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm +++ b/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm @@ -273,3 +273,23 @@ void accessZeroElementOk_FP(NSMutableDictionary* mDict) { NSString* key = array[0]; addInDictBracketsDefault(mDict, key); } + +void addObjectInMSet(NSMutableSet* mSet, id object) { [mSet addObject:object]; } + +void addObjectInMSetOk(NSMutableSet* mSet) { + addObjectInMSet(mSet, @"somestring"); +} + +void addObjectInMSetBad(NSMutableSet* mSet) { addObjectInMSet(mSet, nil); } + +void removeObjectFromMSet(NSMutableSet* mSet, id object) { + [mSet removeObject:object]; +} + +void removeObjectFromMSetOk(NSMutableSet* mSet) { + removeObjectFromMSet(mSet, @"somestring"); +} + +void removeObjectFromMSetBad(NSMutableSet* mSet) { + removeObjectFromMSet(mSet, nil); +} diff --git a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp index 3a6889ef2..224866cce 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp @@ -3,11 +3,13 @@ codetoanalyze/objcpp/pulse/NPEBasic.mm, accessZeroElementOk_FP, 4, NIL_INSERTION codetoanalyze/objcpp/pulse/NPEBasic.mm, addNilInArrayBad, 0, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,passed as argument to `NSMutableArray.addObject:` (modelled),return from call to `NSMutableArray.addObject:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, addNilInDictBad, 2, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,assigned,passed as argument to `NSMutableDictionary.setObject:forKey:` (modelled),return from call to `NSMutableDictionary.setObject:forKey:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, addNilKeyInDictBracketsBad, 2, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,assigned,passed as argument to `mutableDictionary[someKey] = value` (modelled),return from call to `mutableDictionary[someKey] = value` (modelled),invalid access occurs here] +codetoanalyze/objcpp/pulse/NPEBasic.mm, addObjectInMSetBad, 0, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `addObjectInMSet` here,parameter `object` of addObjectInMSet,passed as argument to `NSMutableSet.addObject:` (modelled),return from call to `NSMutableSet.addObject:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, addObjectKeyNilInDictBad, 2, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,passed as argument to `NSMutableDictionary.setObject:forKey:` (modelled),return from call to `NSMutableDictionary.setObject:forKey:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, dereferenceNilBad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, dictionaryWithSharedKeySetBad, 2, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,passed as argument to `NSMutableDictionary.dictionaryWithSharedKeySet` (modelled),return from call to `NSMutableDictionary.dictionaryWithSharedKeySet` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, insertNilInArrayBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,passed as argument to `NSMutableArray.insertObject:atIndex:` (modelled),return from call to `NSMutableArray.insertObject:atIndex:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, removeObjectFromDictKeyNilBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `removeObjectFromDict` here,parameter `key` of removeObjectFromDict,passed as argument to `NSMutableDictionary.removeObjectForKey` (modelled),return from call to `NSMutableDictionary.removeObjectForKey` (modelled),invalid access occurs here] +codetoanalyze/objcpp/pulse/NPEBasic.mm, removeObjectFromMSetBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,when calling `removeObjectFromMSet` here,parameter `object` of removeObjectFromMSet,passed as argument to `NSMutableSet.removeObject:` (modelled),return from call to `NSMutableSet.removeObject:` (modelled),invalid access occurs here] codetoanalyze/objcpp/pulse/NPEBasic.mm, replaceNilInArrayBad, 1, NIL_INSERTION_INTO_COLLECTION, no_bucket, ERROR, [is the null pointer,passed as argument to `NSMutableArray.replaceObjectAtIndex:withObject:` (modelled),return from call to `NSMutableArray.replaceObjectAtIndex:withObject:` (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]