From c62dd2a0c235ac8b9b52060447d904ad67252fbe Mon Sep 17 00:00:00 2001 From: Jeremy Dubreil Date: Wed, 13 Dec 2017 17:06:10 -0800 Subject: [PATCH] [infer][nullable checker] add models for mutations of mutable dictionaries and mutable arrays Reviewed By: sblackshear Differential Revision: D6559987 fbshipit-source-id: e3175dd --- infer/src/checkers/NullabilityCheck.ml | 8 +++++--- .../codetoanalyze/objc/checkers/Nullable.m | 18 ++++++++++++++++++ .../codetoanalyze/objc/checkers/issues.exp | 6 ++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/infer/src/checkers/NullabilityCheck.ml b/infer/src/checkers/NullabilityCheck.ml index b2e0b07db..ce18107e3 100644 --- a/infer/src/checkers/NullabilityCheck.ml +++ b/infer/src/checkers/NullabilityCheck.ml @@ -44,12 +44,14 @@ module TransferFunctions (CFG : ProcCfg.S) = struct let is_objc_container_add_method : Typ.Procname.t -> bool = let method_prefixes = - [ "arrayWithObjects:" - ; "arrayWithObjects:" + [ "addObject:" ; "arrayByAddingObject:" + ; "arrayWithObjects:" + ; "dictionaryWithObjects:" ; "dictionaryWithObjectsAndKeys:" ; "initWithObjectsAndKeys:" - ; "dictionaryWithObjects:" ] + ; "insertObject:" + ; "setObject:" ] in fun proc_name -> let simplified_callee_pname = Typ.Procname.to_simplified_string proc_name in diff --git a/infer/tests/codetoanalyze/objc/checkers/Nullable.m b/infer/tests/codetoanalyze/objc/checkers/Nullable.m index 0ca925fc5..2d4d52092 100644 --- a/infer/tests/codetoanalyze/objc/checkers/Nullable.m +++ b/infer/tests/codetoanalyze/objc/checkers/Nullable.m @@ -198,4 +198,22 @@ int* __nullable returnsNull(); return [array arrayByAddingObject:[self nullableMethod]]; } +- (NSDictionary*)setNullableObjectInDictionaryBad { + NSMutableDictionary* mutableDict = [NSMutableDictionary dictionary]; + [mutableDict setObject:[self nullableMethod] forKey:@"key"]; // reports here + return mutableDict; +} + +- (NSArray*)addNullableObjectInMutableArrayBad { + NSMutableArray* mutableArray = [[NSMutableArray alloc] init]; + [mutableArray addObject:[self nullableMethod]]; // reports here + return mutableArray; +} + +- (NSArray*)insertNullableObjectInMutableArrayBad { + NSMutableArray* mutableArray = [[NSMutableArray alloc] init]; + [mutableArray insertObject:[self nullableMethod] atIndex:0]; // reports here + return mutableArray; +} + @end diff --git a/infer/tests/codetoanalyze/objc/checkers/issues.exp b/infer/tests/codetoanalyze/objc/checkers/issues.exp index 7d0588927..94a18b848 100644 --- a/infer/tests/codetoanalyze/objc/checkers/issues.exp +++ b/infer/tests/codetoanalyze/objc/checkers/issues.exp @@ -2,6 +2,8 @@ codetoanalyze/objc/checkers/Nullable.m, T_FP_dereferenceNonnullFieldAfterTestFor codetoanalyze/objc/checkers/Nullable.m, T_FP_dereferenceNonnullFieldAfterTestForNullOkay, 2, NULL_DEREFERENCE, [start of procedure FP_dereferenceNonnullFieldAfterTestForNullOkay,Condition is true] codetoanalyze/objc/checkers/Nullable.m, T_URLWithStringOkay, 2, DEAD_STORE, [Write of unused value] codetoanalyze/objc/checkers/Nullable.m, T_URLWithStringOkay, 2, NULL_DEREFERENCE, [start of procedure URLWithStringOkay,Skipping URLWithString:: function or method not found] +codetoanalyze/objc/checkers/Nullable.m, T_addNullableObjectInMutableArrayBad, 2, NULLABLE_DEREFERENCE, [dereferencing the return of nullableMethod,assignment of the nullable value,definition of nullableMethod] +codetoanalyze/objc/checkers/Nullable.m, T_addNullableObjectInMutableArrayBad, 2, NULL_DEREFERENCE, [start of procedure addNullableObjectInMutableArrayBad,start of procedure nullableMethod,return from a call to T_nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_assignNonnullFieldToNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnullField is assigned null here] codetoanalyze/objc/checkers/Nullable.m, T_assignUnnanotatedFieldToNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is assigned null here] codetoanalyze/objc/checkers/Nullable.m, T_createArrayByAddingNilBad, 2, NULLABLE_DEREFERENCE, [dereferencing the return of nullableMethod,assignment of the nullable value,definition of nullableMethod] @@ -13,6 +15,8 @@ codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestFo codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceUnnanotatedFieldAfterTestForNullBad,Condition is true] codetoanalyze/objc/checkers/Nullable.m, T_indirectNullableKeyInNSDictionaryBad, 3, NULLABLE_DEREFERENCE, [dereference of &nullableKeyString,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_indirectNullableKeyInNSDictionaryBad, 3, PREMATURE_NIL_TERMINATION_ARGUMENT, [start of procedure indirectNullableKeyInNSDictionaryBad,start of procedure nullableMethod,return from a call to T_nullableMethod,Message description with receiver nil returns nil.] +codetoanalyze/objc/checkers/Nullable.m, T_insertNullableObjectInMutableArrayBad, 2, NULLABLE_DEREFERENCE, [dereferencing the return of nullableMethod,assignment of the nullable value,definition of nullableMethod] +codetoanalyze/objc/checkers/Nullable.m, T_insertNullableObjectInMutableArrayBad, 2, NULL_DEREFERENCE, [start of procedure insertNullableObjectInMutableArrayBad,start of procedure nullableMethod,return from a call to T_nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_nullableKeyInNSDictionaryBad, 2, NULLABLE_DEREFERENCE, [dereference of &nullableKey,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_nullableKeyInNSDictionaryBad, 2, PREMATURE_NIL_TERMINATION_ARGUMENT, [start of procedure nullableKeyInNSDictionaryBad,start of procedure nullableMethod,return from a call to T_nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_nullableKeyInNSDictionaryInitBad, 2, NULLABLE_DEREFERENCE, [dereference of &nullableKey,assignment of the nullable value,definition of nullableMethod] @@ -30,6 +34,8 @@ codetoanalyze/objc/checkers/Nullable.m, T_nullableValueInNSDictionaryInitLiteral codetoanalyze/objc/checkers/Nullable.m, T_reassigningNullableObjectOkay, 1, DEAD_STORE, [Write of unused value] codetoanalyze/objc/checkers/Nullable.m, T_secondElementNullableObjectInNSArrayBad, 3, NULLABLE_DEREFERENCE, [dereference of &nullableObject,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_secondElementNullableObjectInNSArrayBad, 3, NULL_DEREFERENCE, [start of procedure secondElementNullableObjectInNSArrayBad,start of procedure nullableMethod,return from a call to T_nullableMethod] +codetoanalyze/objc/checkers/Nullable.m, T_setNullableObjectInDictionaryBad, 2, NULLABLE_DEREFERENCE, [dereferencing the return of nullableMethod,assignment of the nullable value,definition of nullableMethod] +codetoanalyze/objc/checkers/Nullable.m, T_setNullableObjectInDictionaryBad, 2, NULL_DEREFERENCE, [start of procedure setNullableObjectInDictionaryBad,start of procedure nullableMethod,return from a call to T_nullableMethod] codetoanalyze/objc/checkers/Nullable.m, T_testNonnullFieldForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnullField is compared to null here] codetoanalyze/objc/checkers/Nullable.m, T_testUnnanotatedFieldForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here] codetoanalyze/objc/checkers/Nullable.m, objc_blockT_DeadStoreFP_testUnnanotatedFieldInClosureBad_1, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here]