[infer][clang] the nullable checker should not warn on pointer re-assignment

Summary: This is a hack to removes most of the false positives of this checker in Objective C.

Reviewed By: sblackshear

Differential Revision: D6239914

fbshipit-source-id: 1cf05de
master
Jeremy Dubreil 7 years ago committed by Facebook Github Bot
parent 29fe7d1689
commit ebea2a6ba1

@ -105,6 +105,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let exec_instr ((_, checked_pnames) as astate) proc_data _ (instr: HilInstr.t) : Domain.astate = let exec_instr ((_, checked_pnames) as astate) proc_data _ (instr: HilInstr.t) : Domain.astate =
let is_pointer_assignment tenv lhs rhs =
HilExp.is_null_literal rhs
(* the rhs has type int when assigning the lhs to null *)
|| Option.equal Typ.equal (AccessPath.get_typ lhs tenv) (HilExp.get_typ tenv rhs)
(* the lhs and rhs have the same type in the case of pointer assignment
but the types are different when assigning the pointee *)
in
match instr with match instr with
| Call (Some ret_var, Direct callee_pname, _, _, _) | Call (Some ret_var, Direct callee_pname, _, _, _)
when NullCheckedPname.mem callee_pname checked_pnames -> when NullCheckedPname.mem callee_pname checked_pnames ->
@ -132,6 +139,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
-> ( -> (
Option.iter Option.iter
~f:(fun (nullable_ap, call_sites) -> ~f:(fun (nullable_ap, call_sites) ->
if not (is_pointer_assignment proc_data.ProcData.tenv nullable_ap rhs) then
(* TODO (T22426288): Undertand why the pointer derference and the pointer
assignment have the same HIL representation *)
report_nullable_dereference nullable_ap call_sites proc_data loc) report_nullable_dereference nullable_ap call_sites proc_data loc)
(longest_nullable_prefix lhs astate) ; (longest_nullable_prefix lhs astate) ;
match rhs with match rhs with

@ -7,15 +7,13 @@ codetoanalyze/cpp/nullable/example.cpp, T_dereference_unnanotated_field_after_te
codetoanalyze/cpp/nullable/example.cpp, T_dereference_unnanotated_field_after_test_for_null_bad, 2, NULL_DEREFERENCE, [start of procedure dereference_unnanotated_field_after_test_for_null_bad,Condition is true] codetoanalyze/cpp/nullable/example.cpp, T_dereference_unnanotated_field_after_test_for_null_bad, 2, NULL_DEREFERENCE, [start of procedure dereference_unnanotated_field_after_test_for_null_bad,Condition is true]
codetoanalyze/cpp/nullable/example.cpp, T_test_nonnull_field_for_null_bad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnull_field is compared to null here] codetoanalyze/cpp/nullable/example.cpp, T_test_nonnull_field_for_null_bad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnull_field is compared to null here]
codetoanalyze/cpp/nullable/example.cpp, T_test_unnanotated_field_for_null_bad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotated_field is compared to null here] codetoanalyze/cpp/nullable/example.cpp, T_test_unnanotated_field_for_null_bad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotated_field is compared to null here]
codetoanalyze/cpp/nullable/method.cpp, FP_reAssigningNullableValueOk, 1, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/nullable/method.cpp, FP_reAssigningNullableValueOk, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullPointer]
codetoanalyze/cpp/nullable/method.cpp, assignNullableValueBad, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullPointer] codetoanalyze/cpp/nullable/method.cpp, assignNullableValueBad, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullPointer]
codetoanalyze/cpp/nullable/method.cpp, assignNullableValueBad, 2, NULL_DEREFERENCE, [start of procedure assignNullableValueBad(),start of procedure mayReturnNullPointer,Condition is true,return from a call to T_mayReturnNullPointer] codetoanalyze/cpp/nullable/method.cpp, assignNullableValueBad, 2, NULL_DEREFERENCE, [start of procedure assignNullableValueBad(),start of procedure mayReturnNullPointer,Condition is true,return from a call to T_mayReturnNullPointer]
codetoanalyze/cpp/nullable/method.cpp, avoidDoubleReportingBad, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, avoidDoubleReportingBad, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, avoidDoubleReportingBad, 2, NULL_DEREFERENCE, [start of procedure avoidDoubleReportingBad(),start of procedure mayReturnNullObject,Condition is true,return from a call to T_mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, avoidDoubleReportingBad, 2, NULL_DEREFERENCE, [start of procedure avoidDoubleReportingBad(),start of procedure mayReturnNullObject,Condition is true,return from a call to T_mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, callMethodOnNullableObjectBad, 1, NULLABLE_DEREFERENCE, [deference of n$2,definition of mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, callMethodOnNullableObjectBad, 1, NULLABLE_DEREFERENCE, [deference of n$2,definition of mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, callMethodOnNullableObjectBad, 1, NULL_DEREFERENCE, [start of procedure callMethodOnNullableObjectBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, callMethodOnNullableObjectBad, 1, NULL_DEREFERENCE, [start of procedure callMethodOnNullableObjectBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, callMethodOnNullableObjectOk, 2, NULL_TEST_AFTER_DEREFERENCE, [start of procedure callMethodOnNullableObjectOk(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,Condition is false] codetoanalyze/cpp/nullable/method.cpp, callMethodOnNullableObjectOkay, 2, NULL_TEST_AFTER_DEREFERENCE, [start of procedure callMethodOnNullableObjectOkay(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,Condition is false]
codetoanalyze/cpp/nullable/method.cpp, dereferenceFieldOfNullableObjectBad, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, dereferenceFieldOfNullableObjectBad, 2, NULLABLE_DEREFERENCE, [deference of &p,assignment of the nullable value,definition of mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, dereferenceFieldOfNullableObjectBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceFieldOfNullableObjectBad(),start of procedure mayReturnNullObject,Condition is true,return from a call to T_mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, dereferenceFieldOfNullableObjectBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceFieldOfNullableObjectBad(),start of procedure mayReturnNullObject,Condition is true,return from a call to T_mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, methodAlwaysCheckedForNullOkay, 1, NULL_TEST_AFTER_DEREFERENCE, [start of procedure methodAlwaysCheckedForNullOkay(),Condition is true,start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,Condition is false] codetoanalyze/cpp/nullable/method.cpp, methodAlwaysCheckedForNullOkay, 1, NULL_TEST_AFTER_DEREFERENCE, [start of procedure methodAlwaysCheckedForNullOkay(),Condition is true,start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,Condition is false]
@ -32,6 +30,8 @@ codetoanalyze/cpp/nullable/method.cpp, nullableAssignmentInOneBranchBad, 7, NULL
codetoanalyze/cpp/nullable/method.cpp, onlyReportOnceBad, 1, NULLABLE_DEREFERENCE, [deference of n$6,definition of mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, onlyReportOnceBad, 1, NULLABLE_DEREFERENCE, [deference of n$6,definition of mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, onlyReportOnceBad, 1, NULL_DEREFERENCE, [start of procedure onlyReportOnceBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, onlyReportOnceBad, 1, NULL_DEREFERENCE, [start of procedure onlyReportOnceBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, onlyReportOnceBad, 3, NULL_DEREFERENCE, [start of procedure onlyReportOnceBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,start of procedure doSomething,return from a call to T_doSomething,start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, onlyReportOnceBad, 3, NULL_DEREFERENCE, [start of procedure onlyReportOnceBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,start of procedure doSomething,return from a call to T_doSomething,start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, reassigningNullablePointerOkay, 1, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/nullable/method.cpp, reassigningNullablePointerToNullOkay, 1, DEAD_STORE, [Write of unused value]
codetoanalyze/cpp/nullable/method.cpp, reportsViolationInNotNullElseBranchBad, 1, NULL_TEST_AFTER_DEREFERENCE, [start of procedure reportsViolationInNotNullElseBranchBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,Condition is false] codetoanalyze/cpp/nullable/method.cpp, reportsViolationInNotNullElseBranchBad, 1, NULL_TEST_AFTER_DEREFERENCE, [start of procedure reportsViolationInNotNullElseBranchBad(),start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject,Condition is false]
codetoanalyze/cpp/nullable/method.cpp, reportsViolationInNotNullElseBranchBad, 3, NULLABLE_DEREFERENCE, [deference of n$5,definition of mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, reportsViolationInNotNullElseBranchBad, 3, NULLABLE_DEREFERENCE, [deference of n$5,definition of mayReturnNullObject]
codetoanalyze/cpp/nullable/method.cpp, reportsViolationInNotNullElseBranchBad, 3, NULL_DEREFERENCE, [start of procedure reportsViolationInNotNullElseBranchBad(),start of procedure mayReturnNullObject,Condition is true,return from a call to T_mayReturnNullObject,Condition is false,start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject] codetoanalyze/cpp/nullable/method.cpp, reportsViolationInNotNullElseBranchBad, 3, NULL_DEREFERENCE, [start of procedure reportsViolationInNotNullElseBranchBad(),start of procedure mayReturnNullObject,Condition is true,return from a call to T_mayReturnNullObject,Condition is false,start of procedure mayReturnNullObject,Condition is false,return from a call to T_mayReturnNullObject]

@ -43,17 +43,22 @@ void assignNullableValueBad(T* t) {
*p = 42; *p = 42;
} }
void FP_reAssigningNullableValueOk(T* t) { void reassigningNullablePointerOkay(T* t) {
int* p = t->mayReturnNullPointer(); int* p = t->mayReturnNullPointer();
p = new int; p = new int; // does not report here
*p = 42; *p = 42; // does not report here
}
void reassigningNullablePointerToNullOkay(T* t) {
int* p = t->mayReturnNullPointer();
p = nullptr; // does not report here
} }
void callMethodOnNullableObjectBad(T* t) { void callMethodOnNullableObjectBad(T* t) {
t->mayReturnNullObject()->doSomething(); t->mayReturnNullObject()->doSomething();
} }
void callMethodOnNullableObjectOk(T* t) { void callMethodOnNullableObjectOkay(T* t) {
T* p = t->mayReturnNullObject(); T* p = t->mayReturnNullObject();
if (p != nullptr) { if (p != nullptr) {
p->doSomething(); p->doSomething();
@ -72,8 +77,8 @@ void methodCallOnFieldOfNullableObjectBad(T* t) {
void avoidDoubleReportingBad(T* t) { void avoidDoubleReportingBad(T* t) {
T* p = t->mayReturnNullObject(); T* p = t->mayReturnNullObject();
p->doSomething(); // should report here p->doSomething(); // reports here
p->doSomething(); // should not report here p->doSomething(); // does not report here
} }
void nullableAssignmentInOneBranchBad(T* t) { void nullableAssignmentInOneBranchBad(T* t) {

@ -108,7 +108,12 @@ int* __nullable returnsNull();
- (NSString*)dereferenceNullableMethodOkay { - (NSString*)dereferenceNullableMethodOkay {
NSObject* object = [self nullableMethod]; NSObject* object = [self nullableMethod];
return [object description]; return [object description]; // does not report here
}
- (void)reassigningNullableObjectOkay {
NSObject* object = [self nullableMethod];
object = nil; // does not report here
} }
@end @end

@ -7,6 +7,7 @@ codetoanalyze/objc/checkers/Nullable.m, T_dereferenceNullableFunctionBad, 2, NUL
codetoanalyze/objc/checkers/Nullable.m, T_dereferenceNullableFunctionBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceNullableFunctionBad,Skipping returnsNull(): function or method not found] codetoanalyze/objc/checkers/Nullable.m, T_dereferenceNullableFunctionBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceNullableFunctionBad,Skipping returnsNull(): function or method not found]
codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here] codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here]
codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceUnnanotatedFieldAfterTestForNullBad,Condition is true] codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceUnnanotatedFieldAfterTestForNullBad,Condition is true]
codetoanalyze/objc/checkers/Nullable.m, T_reassigningNullableObjectOkay, 1, DEAD_STORE, [Write of unused value]
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_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, 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] codetoanalyze/objc/checkers/Nullable.m, objc_blockT_DeadStoreFP_testUnnanotatedFieldInClosureBad_1, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here]

Loading…
Cancel
Save