From 73b4409e6ff6d9694a12985450535bbf6b84d452 Mon Sep 17 00:00:00 2001 From: Jeremy Dubreil Date: Wed, 3 Jan 2018 17:48:45 -0800 Subject: [PATCH] [infer][nullable checker] no longer propagate the nullability when the lhs is not a pointer type Summary: The checker should only propagate the nullablility on the lhs when of pointer type. Reviewed By: sblackshear Differential Revision: D6630294 fbshipit-source-id: 07fe3d6 --- infer/src/checkers/NullabilityCheck.ml | 9 ++++-- .../codetoanalyze/objc/nullable/Examples.m | 29 +++++++++++++++++++ .../codetoanalyze/objc/nullable/issues.exp | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/infer/src/checkers/NullabilityCheck.ml b/infer/src/checkers/NullabilityCheck.ml index 7eafc2bb2..69b58d6bf 100644 --- a/infer/src/checkers/NullabilityCheck.ml +++ b/infer/src/checkers/NullabilityCheck.ml @@ -221,8 +221,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct check_ap proc_data loc receiver astate | Call (_, Direct callee_pname, args, _, loc) when is_objc_container_add_method callee_pname -> check_nil_in_objc_container proc_data loc args astate - | Call (Some ret_var, Direct callee_pname, (HilExp.AccessPath receiver) :: _, _, _) - when is_objc_instance_method callee_pname -> ( + | Call + ( Some ((_, ret_typ) as ret_var) + , Direct callee_pname + , (HilExp.AccessPath receiver) :: _ + , _ + , _ ) + when Typ.is_pointer ret_typ && is_objc_instance_method callee_pname -> ( match longest_nullable_prefix receiver astate with | None -> astate diff --git a/infer/tests/codetoanalyze/objc/nullable/Examples.m b/infer/tests/codetoanalyze/objc/nullable/Examples.m index 733d3d48c..0cbe77274 100644 --- a/infer/tests/codetoanalyze/objc/nullable/Examples.m +++ b/infer/tests/codetoanalyze/objc/nullable/Examples.m @@ -10,8 +10,15 @@ int* __nullable returnsNull(); +typedef struct s_ { + int x; +} S; + @interface T : NSObject - (NSObject* _Nullable)nullableMethod; +- (T* _Nullable)nullableT; +@property(nonatomic) S structProperty; +@property(nonatomic) S* pointerProperty; @end @implementation T { @@ -216,6 +223,28 @@ int* __nullable returnsNull(); return mutableArray; } +- (NSArray*)propagateNullabilityOnMethodCallBad { + NSObject* nullableObject = [self nullableMethod]; + NSString* nullableString = + [nullableObject description]; // returns nil if nullableObject is nil + return @[ nullableString ]; // reports here +} + +- (S*)shouldPropagateNullabilityOnPointerTypeBad { + T* nullableT = [self nullableT]; + S* s = nullableT.pointerProperty; // returns nil when nullableT is nil + s->x = 42; // reports here + return s; +} + +- (S)shouldNotPropagateNullabilityOnNonPointerTypeGood { + T* nullableT = [self nullableT]; + S s = + nullableT.structProperty; // returns an empty struct when nullabeT is nil + s.x = 42; // does not report here + return s; +} + @end @protocol P diff --git a/infer/tests/codetoanalyze/objc/nullable/issues.exp b/infer/tests/codetoanalyze/objc/nullable/issues.exp index 31075d772..dc870cc1a 100644 --- a/infer/tests/codetoanalyze/objc/nullable/issues.exp +++ b/infer/tests/codetoanalyze/objc/nullable/issues.exp @@ -14,8 +14,10 @@ codetoanalyze/objc/nullable/Examples.m, T_nullableObjectInNSArrayBad, 2, NULLABL codetoanalyze/objc/nullable/Examples.m, T_nullableValueInNSDictionaryBad, 2, NULLABLE_DEREFERENCE, [dereference of &nullableValue,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/nullable/Examples.m, T_nullableValueInNSDictionaryInitBad, 2, NULLABLE_DEREFERENCE, [dereference of &nullableValue,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/nullable/Examples.m, T_nullableValueInNSDictionaryInitLiteralBad, 2, NULLABLE_DEREFERENCE, [dereference of &nullableValue,assignment of the nullable value,definition of nullableMethod] +codetoanalyze/objc/nullable/Examples.m, T_propagateNullabilityOnMethodCallBad, 4, NULLABLE_DEREFERENCE, [dereference of &nullableString,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/nullable/Examples.m, T_secondElementNullableObjectInNSArrayBad, 3, NULLABLE_DEREFERENCE, [dereference of &nullableObject,assignment of the nullable value,definition of nullableMethod] codetoanalyze/objc/nullable/Examples.m, T_setNullableObjectInDictionaryBad, 2, NULLABLE_DEREFERENCE, [dereferencing the return of nullableMethod,assignment of the nullable value,definition of nullableMethod] +codetoanalyze/objc/nullable/Examples.m, T_shouldPropagateNullabilityOnPointerTypeBad, 3, NULLABLE_DEREFERENCE, [dereference of &s,assignment of the nullable value,definition of nullableT] codetoanalyze/objc/nullable/Examples.m, T_testNonnullFieldForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnullField is compared to null here] codetoanalyze/objc/nullable/Examples.m, T_testUnnanotatedFieldForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here] codetoanalyze/objc/nullable/Examples.m, callNullableMethodFromProtocolBad, 2, NULLABLE_DEREFERENCE, [dereference of &nullableObject,assignment of the nullable value,definition of nullableMethod]