2012.12.13 00:12 "Re: [Tiff] Dealing with unportability of malloc(0)", by Bob Friesenhahn
I noticed that Bob Friesenhahn recently committed this change to make _TIFFmalloc() behave the same on platforms where malloc(0) returns a zero-sized chunk of memory as it does on platforms where the same call returns NULL:
As far as I am aware, the malloc() on most systems returns NULL for a size of zero. We could create a test to confirm this if necessary. If my belief is true, then my code change simply assured the common case and avoids the possible "implementation dependent" behavior.
[ chop ]
The reason I think the never-null convention is preferable is that the null-for-zero convention tends to require doctoring up call sites. The typical pattern is
ptr = _TIFFmalloc(some_request);
if (ptr == NULL)
// throw error
If there's any possibility that some_request is (validly) zero, this code is now broken, because it will throw errors when it should not.
Can you think of such valid cases?
Now, libtiff is more fortunate than many projects in that most places that might have this problem are calling _TIFFCheckMalloc, which means that there are fewer places to fix than there might be. But I doubt
that that's really the only one. In fact, if that *were* the only one, we'd not need this patch at all, because that call site already tries to dodge the platform dependency.
... unfortunately, it does so incorrectly. _TIFFCheckMalloc is coded to call _TIFFCheckRealloc, and the latter is miswritten so that it is guaranteed to throw error for a zero request, no matter which behavior the underlying malloc and realloc calls have.
And, just to add insult to injury, first it will leak the old block if there is one, since neither realloc() nor free() will get called.
None of this is terribly hard to fix, but first we need a policy decision about which platform-specific behavior we want to standardize on. I gave my argument above, does anyone want to advocate for the other way? Are there pieces of libtiff where the null-for-zero convention is preferable?
One reason why I like an argument of zero to produce NULL is that often there is a chunk of complex code which computes the size to allocate. In order to assure security, this complex code also needs to detect overflow conditions. Regardless, the decision then needs to be made how to report the overflow condition. A simple approach I have used in the past is to arrange to pass zero to the memory allocation function since there was always already error handling for memory allocation failure. This allows one error reporting path to handle both types of errors.
Another reason why I like an argument of zero to produce NULL is that zero is a very common value which often reflects an uninitialized condition. It is useful for such conditions to result in a normally-handled error response.
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/