39
39
#include < __type_traits/type_identity.h>
40
40
#include < __utility/forward.h>
41
41
#include < __utility/move.h>
42
+ #include < __utility/private_constructor_tag.h>
42
43
#include < cstddef>
43
44
44
45
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -301,6 +302,21 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
301
302
302
303
private:
303
304
__compressed_pair<pointer, deleter_type> __ptr_;
305
+ #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
306
+ // Under the "bounded unique_ptr" ABI, we store the size of the allocation when it is known.
307
+ // The size of the allocation can be known when unique_ptr is created via make_unique or a
308
+ // similar API, however it can't be known when constructed with e.g.
309
+ //
310
+ // unique_ptr<T[]> ptr(new T[3]);
311
+ //
312
+ // In that case, we don't know the size of the allocation from within the unique_ptr.
313
+ // Semantically, we'd need to store `optional<size_t>`. However, since that is really
314
+ // heavy weight, we instead store a size_t and use 0 as a magic value meaning that we
315
+ // don't know the size. This means that we can't catch OOB accesses inside a unique_ptr
316
+ // with a 0-sized allocation, however since this is a degenerate case, it doesn't matter
317
+ // in practice.
318
+ size_t __size_ = 0 ;
319
+ #endif
304
320
305
321
template <class _From >
306
322
struct _CheckArrayPointerConversion : is_same<_From, pointer> {};
@@ -397,6 +413,18 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
397
413
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr (unique_ptr&& __u) _NOEXCEPT
398
414
: __ptr_(__u.release(), std::forward<deleter_type>(__u.get_deleter())) {}
399
415
416
+ // Constructor used by make_unique & friends to pass the size that was allocated
417
+ template <class _Ptr >
418
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr (
419
+ __private_constructor_tag, _Ptr __ptr, size_t __size) _NOEXCEPT
420
+ : __ptr_(__ptr, __value_init_tag())
421
+ #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
422
+ ,
423
+ __size_ (__size)
424
+ #endif
425
+ {
426
+ }
427
+
400
428
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator =(unique_ptr&& __u) _NOEXCEPT {
401
429
reset (__u.release ());
402
430
__ptr_.second () = std::forward<deleter_type>(__u.get_deleter ());
@@ -434,6 +462,10 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
434
462
}
435
463
436
464
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t <_Tp> operator [](size_t __i) const {
465
+ #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
466
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (
467
+ __size_ == 0 || __i < __size_, " unique_ptr<T[]>::operator[](index): index out of range" );
468
+ #endif
437
469
return __ptr_.first ()[__i];
438
470
}
439
471
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get () const _NOEXCEPT { return __ptr_.first (); }
@@ -624,7 +656,7 @@ template <class _Tp>
624
656
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound
625
657
make_unique (size_t __n) {
626
658
typedef __remove_extent_t <_Tp> _Up;
627
- return unique_ptr<_Tp>(new _Up[__n]());
659
+ return unique_ptr<_Tp>(__private_constructor_tag (), new _Up[__n](), __n );
628
660
}
629
661
630
662
template <class _Tp , class ... _Args>
@@ -643,7 +675,7 @@ make_unique_for_overwrite() {
643
675
template <class _Tp >
644
676
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound
645
677
make_unique_for_overwrite (size_t __n) {
646
- return unique_ptr<_Tp>(new __remove_extent_t <_Tp>[__n]);
678
+ return unique_ptr<_Tp>(__private_constructor_tag (), new __remove_extent_t <_Tp>[__n], __n );
647
679
}
648
680
649
681
template <class _Tp , class ... _Args>
0 commit comments