Summary: Added some basic examples for Objective-C we want to address next in pulse nullptr dereference analysis. In particular, we should not get a `nil` dereference error when we call a method on `nil`, except if the method returns a non-POD (Plain Old Data) type. Reviewed By: ezgicicek Differential Revision: D26053402 fbshipit-source-id: 66f4600c3master
parent
802dce02d1
commit
e0f0022fa1
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
#include <memory>
|
||||
|
||||
@interface SomeObject : NSObject
|
||||
|
||||
@property int x;
|
||||
@property std::shared_ptr<int> ptr;
|
||||
|
||||
- (int)returnsPOD;
|
||||
|
||||
- (std::shared_ptr<int>)returnsnonPOD;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SomeObject
|
||||
|
||||
- (int)returnsPOD {
|
||||
return _x;
|
||||
}
|
||||
|
||||
- (std::shared_ptr<int>)returnsnonPOD {
|
||||
return std::shared_ptr<int>(new int(_x));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int dereferenceNilBad() {
|
||||
int* int_ptr = nil;
|
||||
return *int_ptr;
|
||||
}
|
||||
|
||||
int FP_testCallMethodReturnsPODOk() {
|
||||
SomeObject* obj = nil;
|
||||
return [obj returnsPOD];
|
||||
}
|
||||
|
||||
std::shared_ptr<int> testCallMethodReturnsnonPODBad() {
|
||||
SomeObject* obj = nil;
|
||||
std::shared_ptr<int> d = [obj returnsnonPOD]; // UB
|
||||
return d;
|
||||
}
|
||||
|
||||
int FP_testAccessPropertyAccessorOk() {
|
||||
SomeObject* obj = nil;
|
||||
return obj.x; // calls property accessor method
|
||||
}
|
||||
|
||||
std::shared_ptr<int> testAccessPropertyAccessorBad() {
|
||||
SomeObject* obj = nil;
|
||||
return obj.ptr; // calls property accessor method, but return type is non-POD
|
||||
}
|
||||
|
||||
int methodReturnsPOD(SomeObject* obj) { return [obj returnsPOD]; };
|
||||
|
||||
int FP_methodReturnsPODNilOk() { return methodReturnsPOD(nil); };
|
||||
|
||||
int methodReturnsPODNotNilOK() {
|
||||
SomeObject* o = [SomeObject new];
|
||||
return methodReturnsPOD(o);
|
||||
}
|
@ -1,3 +1,9 @@
|
||||
codetoanalyze/objcpp/pulse/AllocPatternMemLeak.mm, A.create_no_release_leak_bad, 1, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `ABFDataCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
|
||||
codetoanalyze/objcpp/pulse/NPEBasic.mm, FP_methodReturnsPODNilOk, 0, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,when calling `methodReturnsPOD` here,parameter `obj` of methodReturnsPOD,when calling `SomeObject.returnsPOD` here,parameter `self` of SomeObject.returnsPOD,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/NPEBasic.mm, FP_testAccessPropertyAccessorOk, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,when calling `SomeObject.x` here,parameter `self` of SomeObject.x,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/NPEBasic.mm, FP_testCallMethodReturnsPODOk, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,when calling `SomeObject.returnsPOD` here,parameter `self` of SomeObject.returnsPOD,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/NPEBasic.mm, dereferenceNilBad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/NPEBasic.mm, testAccessPropertyAccessorBad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,when calling `SomeObject.ptr` here,parameter `self` of SomeObject.ptr,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/NPEBasic.mm, testCallMethodReturnsnonPODBad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,assigned,when calling `SomeObject.returnsnonPOD` here,parameter `self` of SomeObject.returnsnonPOD,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/use_after_delete.mm, PulseTest.deref_deleted_in_objc_method_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,passed as argument to `new` (modelled),return from call to `new` (modelled),assigned,was invalidated by `delete`,use-after-lifetime part of the trace starts here,passed as argument to `new` (modelled),return from call to `new` (modelled),assigned,when calling `Simple::Simple` here,parameter `__param_0` of Simple::Simple,invalid access occurs here]
|
||||
codetoanalyze/objcpp/pulse/use_after_delete.mm, deref_deleted_bad, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,passed as argument to `new` (modelled),return from call to `new` (modelled),assigned,was invalidated by `delete`,use-after-lifetime part of the trace starts here,passed as argument to `new` (modelled),return from call to `new` (modelled),assigned,when calling `Simple::Simple` here,parameter `__param_0` of Simple::Simple,invalid access occurs here]
|
||||
|
Loading…
Reference in new issue