Title
Negative array bound in a new-expression
Status
cd3
Section
7.6.2.8 [expr.new]
Submitter
Mike Miller

Created on 2012-02-12.00:00:00 last changed 122 months ago

Messages

Date: 2012-10-15.00:00:00

Proposed resolution (October, 2012):

  1. Change 6.8.4 [basic.compound] paragraph 2 as follows:

  2. These methods of constructing types can be applied recursively; restrictions are mentioned in 9.3.4.2 [dcl.ptr], 9.3.4.5 [dcl.array], 9.3.4.6 [dcl.fct], and 9.3.4.3 [dcl.ref]. Constructing a type such that the number of bytes in its object representation exceeds the maximum value representable in the type std::size_t (17.2 [support.types]) is ill-formed.
  3. Change 7.6.2.8 [expr.new] paragraph 7 as follows:

  4. The expression in a noptr-new-declarator is erroneous if:

    • the expression is of non-class type and its value before converting to std::size_t is less than zero;

    • the expression is of class type and its value before application of the second standard conversion (12.2.4.2.3 [over.ics.user]) [Footnote: If the conversion function returns a signed integer type, the second standard conversion converts to the unsigned type std::size_t and thus thwarts any attempt to detect a negative value afterwards. —end footnote] is less than zero;

    • its value is such that the size of the allocated object would exceed the implementation-defined limit (annex Clause Annex B [implimits]); or

    • the new-initializer is a braced-init-list and the number of array elements for which initializers are provided (including the terminating '\0' in a string literal (5.13.5 [lex.string])) exceeds the number of elements to initialize.

    If the expression, after converting to std::size_t, is a core constant expression and the expression is erroneous, the program is ill-formed. Otherwise, a new-expression with an erroneous expression does not call an allocation function and terminates by throwing an exception of a type that would match a handler (14.4 [except.handle]) of type std::bad_array_new_length (17.6.4.2 [new.badlength]). When the value of the expression in a noptr-new-declarator is zero, the allocation function is called to allocate an array with no elements. If the value of that expression is less than zero or such that the size of the allocated object would exceed the implementation-defined limit, or if the new-initializer is a braced-init-list for which the number of initializer-clauses exceeds the number of elements to initialize, no storage is obtained and the new-expression terminates by throwing an exception of a type that would match a handler (14.4 [except.handle]) of type std::bad_array_new_length (17.6.4.2 [new.badlength]).

(This resolution also resolves issue 1559.)

Date: 2012-08-15.00:00:00

Additional note (August, 2012):

The goal for addressing this issue should be that an attempt to use an invalid bound (negative, greater than the maximum allowed, or more than the number implied by the initializer) will be ill-formed when the bound is a compile-time constant and will result in an exception otherwise.

Date: 2013-04-15.00:00:00

[Accepted at the April, 2013 meeting.]

Currently, 7.6.2.8 [expr.new] paragraph 7 requires that an attempt to allocate an array with a negative length be diagnosed:

If the value of that expression is less than zero or such that the size of the allocated object would exceed the implementation-defined limit, or if the new-initializer is a braced-init-list for which the number of initializer-clauses exceeds the number of elements to initialize, no storage is obtained and the new-expression terminates by throwing an exception of a type that would match a handler (14.4 [except.handle]) of type std::bad_array_new_length (17.6.4.2 [new.badlength]).

Checking for a negative bound will be lost, however, upon the adoption of paper N3323, as the expression will be converted to std::size_t, an unsigned type. Although the result of this conversion will likely also cause the check to fail (and will always do so when scaled by an element size larger than 1), it is not inconceivable that an implementation could provide a heap that capable of providing more than half the addressable range of std::size_t, and a request for a character array (with an element size of 1) with a negative bound close to LONG_MIN (assuming std::size_t is unsigned long) might actually succeed.

The wording of 7.6.2.8 [expr.new] paragraph 7 should be changed so that the test for a negative bound is applied to the value before conversion to std::size_t, or some other mechanism should be invented to preserve the check for a negative bound.

History
Date User Action Args
2014-03-03 00:00:00adminsetstatus: wp -> cd3
2013-10-14 00:00:00adminsetstatus: accepted -> wp
2013-05-03 00:00:00adminsetstatus: ready -> accepted
2012-11-03 00:00:00adminsetmessages: + msg4049
2012-11-03 00:00:00adminsetstatus: open -> ready
2012-09-24 00:00:00adminsetmessages: + msg3926
2012-02-12 00:00:00admincreate