You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
2.7 KiB

Infer reports null dereference bugs in C, Objective-C and Java. The issue is
about a pointer that can be `null` and it is dereferenced. This leads to a crash
in all the above languages.
### Null dereference in C
Here is an example of an inter-procedural null dereference bug in C:
```c
struct Person {
int age;
int height;
int weight;
};
int get_age(struct Person *who) {
return who->age;
}
int null_pointer_interproc() {
struct Person *joe = 0;
return get_age(joe);
}
```
### Null dereference in Objective-C
In Objective-C, null dereferences are less common than in Java, but they still
happen and their cause can be hidden. In general, passing a message to nil does
not cause a crash and returns `nil`, but dereferencing a pointer directly does
cause a crash as well as calling a `nil` block.C
```objectivec
-(void) foo:(void (^)())callback {
callback();
}
-(void) bar {
[self foo:nil]; //crash
}
```
Moreover, there are functions from the libraries that do not allow `nil` to be
passed as argument. Here are some examples:
```objectivec
-(void) foo {
NSString *str = nil;
NSArray *animals = @[@"horse", str, @"dolphin"]; //crash
}
-(void) bar {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); //can return NULL
...
CFRelease(colorSpace); //crashes if called with NULL
}
```
### Null dereference in Java
Many of Infer's reports of potential NPE's come from code of the form
```java
p = foo(); // foo() might return null
stuff();
p.goo(); // dereferencing p, potential NPE
```
If you see code of this form, then you have several options.
<b> If you are unsure whether or not foo() will return null </b>, you should
ideally i. Change the code to ensure that foo() can not return null ii. Add a
check for whether p is null, and do something other than dereferencing p when it
is null.
Sometimes, in case ii it is not obvious what you should do when p is null. One
possibility (a last option) is to throw an exception, failing early. This can be
done using checkNotNull as in the following code:
```java
// code idiom for failing early
import static com.google.common.base.Preconditions.checkNotNull;
//... intervening code
p = checkNotNull(foo()); // foo() might return null
stuff();
p.goo(); // dereferencing p, potential NPE
```
The call checkNotNull(foo()) will never return null; in case foo() returns null
it fails early by throwing an NPE.
<b> If you are absolutely sure that foo() will not be null </b>, then if you
land your diff this case will no longer be reported after your diff makes it to
master. In the future we might include analysis directives (hey, analyzer, p is
not null!) like in Hack that tell the analyzer the information that you know,
but that is for later.