svn commit: r265367 - head/lib/libc/regex

David Chisnall theraven at FreeBSD.org
Tue May 6 08:06:59 UTC 2014


Bruce,

On 6 May 2014, at 05:46, Bruce Evans <brde at 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.



More information about the svn-src-head mailing list