Bruce,

On 6 May 2014, at 05:46, Bruce Evans <b...@optusnet.com.au> wrote:

> The standard behaviour is undefined.  It cannot be relied on.  From C99
> (n869.txt):
> 
> %        7.20.3.1  The calloc function
> % %        Synopsis
> % %        [#1]
> % %                #include <stdlib.h>
> %                void *calloc(size_t nmemb, size_t size);
> % %        Description
> % %        [#2] The calloc function allocates space  for  an  array  of
> %        nmemb  objects,  each  of  whose size is size.  The space is
> %        initialized to all bits zero.238)
> 
> Oops, there is no object to begin with, so perhaps the behaviour is
> defined after all.  This is unclear.  

You're missing off the next line:

>       • 3  The calloc function returns either a null pointer or a pointer to 
> the allocated space.

Clarifications from WG14 have indicated that this means that calloc() *must* 
return either NULL or enough space for nmemb objects of size size.  The text of 
the standard was not changed in C11 because it seemed to be the consensus of 
library authors that this is obvious from the existing text.  See the CERT 
report from my previous email - in 2002 it was regarded as a security hole (and 
a lack of standards conformance) if your calloc did not do this and all known 
calloc implementations that did not were fixed.

Now, you can argue that either:

- In this case, we can statically prove that the multiplication won't overflow 
so we don't need a check, or

- It is better to do the overflow check on the caller side and increase i-cache 
usage to save some memory zeroing.

But please don't try to argue that it is permitted for calloc() to not 
correctly handle integer overflow.  It is both non-conformant and dangerous for 
it to fail to do so.

> It is also unclear if objects
> can have size too large to represent as a size_t


That is implementation defined, however if sizeof(ptrdiff_t) <= sizeof(size_t) 
then they can not because you must be able to represent the difference between 
any two pointers as a ptrdiff_t[1].  If you want to be pedantic, 
_Static_assert(sizeof(ptrdiff_t) <= sizeof(size_t), "Unsupported platform!") to 
make sure you catch it at compile time if this might change.  

David

[1] This also means, on our platforms, that the maximum size of an object must 
be one byte less than the total size of the address space, as C only defines 
pointer comparisons between valid pointers to the same object and allows 
pointers to be one element past the end of an array.

_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to