On Wed, Sep 02, 2009 at 11:48:21AM -0400, Jim Paris wrote:
>
> Yeah, for functions where it is expected that the passed in param
> be non-NULL, then annotations are definitely the way togo. This
> lets the compiler/checkers validate the callers instead, avoiding
> the need to clutter the methods with irrelevant NULL checks.
Does __attribute__((__nonnull__())) really cover the case we're
concerned about here? As I understand it, it tells the compiler
1) if the caller obviously passes NULL, emit a warning
2) assume that the arguments are non-NULL and optimize away
In other words it will do nothing to prevent a null dereference and
will even make it more likely since non-NULL checks will be skipped.
We should only add the nonnull attribute annotation on methods
where we are not intending to do any checks for non-NULL. They
would already be segfaulting if passed a NULL pointer, so adding
the annotation gives us the static validation of the existing
non-NULL assumption.
For example:
test.c:
--------
#include <stdio.h>
#include <stdlib.h>
void foo(int *a) {
if (a) printf("%d\n", *a);
else printf("(null)\n");
}
__attribute__((__nonnull__ (1)))
void bar(int *a) {
if (a) printf("%d\n", *a);
else printf("(null)\n");
}
int main(void)
{
foo(malloc(1000000000000ULL));
bar(malloc(1000000000000ULL));
return 0;
}
--------
$ gcc -O2 -Wall -Werror -o test test.c
$ ./test
(null)
Segmentation fault
THis is not a case where we would add a non-null annotation - the method
is clearly expecting a NULL parameter as valid since it has a check &
branch to handle that. So using the annotation is not correct.
The prime example of usefulness in libvirt is in the main API glue
- In include/libvirt.h most of the parameters are documented to
be non-NULL. We should *not*, however, annotate libvirt.h since
the implmentation of these APIs is including checks for NULL
and returns a runtime error to the caller in this case. We
don't want the compiler to optimize away these checks
- In the src/driver.h, and the implementations of these driver
APIs eg qemu_driver.c, xen_unified.c, we *should* include
the non-NULL annotation. These methods are relying on the
fact that libvirt.c has already weeded out any NULL pointers
and so don't do any NULL checks themselves.
Regards,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|