[cxx-abi-dev] Run-time array checking

John McCall rjmccall at apple.com
Fri Sep 7 00:41:35 UTC 2012


On Sep 6, 2012, at 4:35 PM, Dennis Handly wrote:
>> From: Mike Herrick <mjh at edg.com>
>> On Sep 6, 2012, at 1:52 PM, John McCall wrote:
>>> For what it's worth, clang has always done this overflow checking
>>> (counting negative counts as an overflow in the signed->unsigned
>>> computation),
> 
> Do you handle large unsigned?  Or you don't have 32 bit?  Or you can't
> allocate 2Gb there?

Clang handles large unsigned.  This is compiler-generated code, so
we do know whether the value has signed type.  We currently do not
take advantage of the __cxa_vec_new routines.

>>>> 2) Have the runtime libraries do the checking and throw
>> 
>>> Well, if we can use (size_t) -1 as a signal value, we don't need any
>>> new entrypoints.  That would be safe on any platform where there are
>>> values of size_t which cannot possibly be allocated
> 
> Right, for 32 bit, you have to have some bytes for instructions.  ;-)
> And for 64 bit, the hardware may not support all bits.

Yeah, the assumption that SIZE_MAX is invalid to allocate is valid on
basically every flat-addressed platform;  it's just not guaranteed by the
standard.  But you can imagine a platform where individual allocations
can't exceed some size that's significantly smaller than a pointer —
for example, on an architecture with segmented or distributed memory,
or on a 64-bit platform that uses a 32-bit size_t because it doesn't care
about supporting >4GB allocations.  It's not a possibility we should
blithely assume away just because it's not true of common platforms.

>>> Don't get me wrong, adding new entrypoints is definitely cleaner.  The
>>> main problem with adding and using new entrypoints is that it means that
>>> old, C++98-compliant code being recompiled will suddenly require new
>>> things from the runtime, which introduces deployment problems.
> 
> Don't you have that for the new Standard, anyway?

Not that I know of; we've been quite careful.  In fact, I know of one area
where the Itanium ABI will probably have to forgo C++11 correctness in
pursuit of our compatibility goals (because of the expansion of the POD
definition).

>>>> 3) A new routine, say __cxa_vec_new_check, that takes a signed
>>>>> element_count
>>> 
>>> It would also need to know how much cookie to add.  The cookie causing
>>> an overflow would certainly be an example of "the value of that
>>> expression is ...  such that the size of the allocated object would
>>> exceed the implementation-defined limit".
> 
> There is a problem with "implementation-defined limit".  For HP-UX there
> are secret hardware limits that the compiler doesn't want to know about.
> There are system config values that limit data allocation.  (Or is the latter
> just the same as bad_alloc and not the new bad_array_new_length?)

Good question.  I guess you could make an abstract argument that an
array allocation which could have succeeded with a different bound
should always produce std::bad_array_new_length, but that would be
a very difficult (and expensive!) guarantee to make in practice.

You could make a serious argument that the only allocations which
*must* throw std::bad_array_new_length rather than just std::bad_alloc
are the cases where you can't call the allocator because the size_t
argument would be negative or otherwise mathematically wrong.
Certainly that would be preferable — if we're creating a new,
constant-sized array of PODs, we should just be able to call the
allocator instead of calling some entrypoint that will check the
length against some implementation limit just so that we can throw
the perfect exception type.

John.


More information about the cxx-abi-dev mailing list