diff --git a/infer/src/pulse/PulseModels.ml b/infer/src/pulse/PulseModels.ml index 72c63c827..5e33b6b58 100644 --- a/infer/src/pulse/PulseModels.ml +++ b/infer/src/pulse/PulseModels.ml @@ -1752,6 +1752,14 @@ module ProcNameDispatcher = struct &:: "setObject:forKeyedSubscript:" <>$ any_arg $+ any_arg $+ capt_arg_payload $--> ObjC.insertion_into_collection_key_or_value ~desc:"mutableDictionary[someKey] = value" + ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSMutableDictionary") + &:: "removeObjectForKey:" <>$ any_arg $+ capt_arg_payload + $--> ObjC.insertion_into_collection_key_or_value + ~desc:"NSMutableDictionary.removeObjectForKey" + ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSMutableDictionary") + &:: "dictionaryWithSharedKeySet:" <>$ capt_arg_payload + $--> ObjC.insertion_into_collection_key_or_value + ~desc:"NSMutableDictionary.dictionaryWithSharedKeySet" ; +map_context_tenv (PatternMatch.ObjectiveC.implements "NSMutableArray") &:: "addObject:" <>$ any_arg $+ capt_arg_payload $--> ObjC.insertion_into_collection_key_or_value ~desc:"NSMutableArray.addObject:" diff --git a/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm b/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm index 916ff5928..3d0a464fb 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm +++ b/infer/tests/codetoanalyze/objcpp/pulse/NPEBasic.mm @@ -207,6 +207,29 @@ void addInDictBracketsOk(NSMutableDictionary* mDict) { mDict[@"key"] = @"somestring"; } +void removeObjectFromDict(NSMutableDictionary* mDict, id key) { + [mDict removeObjectForKey:key]; +} + +void removeObjectFromDictKeyNilBad(NSMutableDictionary* mDict) { + removeObjectFromDict(mDict, nil); +} + +void removeObjectFromDictKeyNotNilOK(NSMutableDictionary* mDict) { + removeObjectFromDict(mDict, @"somestring"); +} + +void dictionaryWithSharedKeySetOk() { + id sharedKeySet = [NSDictionary sharedKeySetForKeys:@[ @"key1", @"key2" ]]; + NSMutableDictionary* mDict = + [NSMutableDictionary dictionaryWithSharedKeySet:sharedKeySet]; +} + +void dictionaryWithSharedKeySetBad() { + NSMutableDictionary* mDict = + [NSMutableDictionary dictionaryWithSharedKeySet:nil]; +} + void testNilMessagingForModelNilNilOK_FP() { addObjectInDict(nil, nil); } void testNilMessagingForModelNilStringOK() { diff --git a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp index f69e0e73e..12e913773 100644 --- a/infer/tests/codetoanalyze/objcpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/objcpp/pulse/issues.exp @@ -5,7 +5,9 @@ codetoanalyze/objcpp/pulse/NPEBasic.mm, addNilInDictBad, 2, NIL_INSERTION_INTO_C 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, 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, 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]