
Jim Paris wrote:
Daniel P. Berrange wrote:
On Wed, Sep 02, 2009 at 12:26:43PM +0200, Jim Meyering wrote:
Daniel Veillard wrote:
On Wed, Sep 02, 2009 at 11:58:07AM +0200, Jim Meyering wrote:
Here's the test just before the else-if in the patch below:
if (conn && conn->driver && STREQ (conn->driver->name, "remote")) {
So, in the else-branch, "conn" is guaranteed to be NULL. And dereferenced.
This may be only a theoretical risk, but if so, the test of "conn" above should be changed to an assertion, and/or the parameter should get the nonnull attribute.
I'm fine with your patch, so that even if code around changes having a gard is IMHO a good thing
Thanks for the quick review. Daniel Berrange said he'd prefer the nonnull approach I mentioned above, so I've just adjusted (caveat, still not tested or even compiled)
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
That's true, in a way.
will even make it more likely since non-NULL checks will be skipped.
Once a parameter is marked nonnull, tools can do a better job of spotting *callers* that might mistakenly pass a corresponding NULL argument. Without nonnull, the compiler could only detect a problem *inside* the function, in the case that we lack adequate protection on a dereferencing expression. For external functions, it's a policy decision. If you say the function is defined only for non-NULL pointers, then you may as well add an assert(ptr != NULL) and __attribute__((nonnull...)). Otherwise, we must perform the test at run-time. Note that memcpy, strcpy, unlink, stat, etc. have parameters that can be marked with the nonnull attribute. That's a plus, because compiler/analyzer tools can then warn callers about misuse, and they needn't be burdened with detecting and diagnosing NULL pointers. Using attribute-nonnull is not an excuse for skipping a "ptr == NULL" test. Rather, it is a way to tell the compiler that we require every caller to ensure that a "ptr" parameter is non-NULL. This has been true of most internal "conn" parameters for some time. There were even quite a few places in the code where "conn" would be dereferenced without first ensuring it is non-NULL, but there was no way to trigger the NULL-deref in those seemingly-erroneous bits of code, because upstream tests ensured non-NULL conn. I spent time adding guards, as I would find those disturbing bits of code. I now think that I should have been adding assertions and/or attribute-nonnull directives, instead. Adding an "assert (ptr != NULL);" is tempting, because then we'd get a pretty diagnostic with filename:lineno rather than just a segfault, whenever this assumption is violated. However, adding a raw "assert" use in library grade code is frowned upon, to say the least.