diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -1590,6 +1590,8 @@ { if (__n > capacity()) { + if (__n > max_size()) + this->__throw_length_error(); allocator_type& __a = this->__alloc(); __split_buffer __v(__n, size(), __a); __swap_out_circular_buffer(__v); @@ -3018,6 +3020,8 @@ { if (__n > capacity()) { + if (__n > max_size()) + this->__throw_length_error(); vector __v(this->get_allocator()); __v.__vallocate(__n); __v.__construct_at_end(this->begin(), this->end()); diff --git a/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp --- a/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/reserve.pass.cpp @@ -16,6 +16,7 @@ #include "test_macros.h" #include "min_allocator.h" +#include "test_allocator.h" int main(int, char**) { @@ -56,6 +57,23 @@ assert(v.capacity() >= 150); } #endif +#ifndef TEST_HAS_NO_EXCEPTIONS + { + std::vector > v; + v.reserve(5); + try { + // A typical implementation would allocate chunks of bits. + // In libc++ the chunk has the same size as the machine word. It is + // reasonable to assume that in practice no implementation would use + // 64 kB or larger chunks. + v.reserve(10 * 65536); + assert(false); + } catch (const std::length_error&) { + // no-op + } + assert(v.capacity() >= 5); + } +#endif return 0; } diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp @@ -67,6 +67,22 @@ assert(is_contiguous_container_asan_correct(v)); } #endif +#ifndef TEST_HAS_NO_EXCEPTIONS + { + std::vector > v; + v.reserve(50); + assert(v.capacity() == 50); + assert(is_contiguous_container_asan_correct(v)); + try { + v.reserve(101); + assert(false); + } catch (const std::length_error&) { + // no-op + } + assert(v.capacity() == 50); + assert(is_contiguous_container_asan_correct(v)); + } +#endif return 0; }