10
10
#ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H
11
11
#define _LIBCPP___MEMORY_UNIQUE_PTR_H
12
12
13
+ #include < __assert>
13
14
#include < __compare/compare_three_way.h>
14
15
#include < __compare/compare_three_way_result.h>
15
16
#include < __compare/three_way_comparable.h>
16
17
#include < __config>
17
18
#include < __functional/hash.h>
18
19
#include < __functional/operations.h>
19
20
#include < __memory/allocator_traits.h> // __pointer
21
+ #include < __memory/array_cookie.h>
20
22
#include < __memory/auto_ptr.h>
21
23
#include < __memory/compressed_pair.h>
24
+ #include < __memory/pointer_traits.h>
22
25
#include < __type_traits/add_lvalue_reference.h>
23
26
#include < __type_traits/common_type.h>
24
27
#include < __type_traits/conditional.h>
27
30
#include < __type_traits/integral_constant.h>
28
31
#include < __type_traits/is_array.h>
29
32
#include < __type_traits/is_assignable.h>
33
+ #include < __type_traits/is_constant_evaluated.h>
30
34
#include < __type_traits/is_constructible.h>
31
35
#include < __type_traits/is_convertible.h>
32
36
#include < __type_traits/is_function.h>
41
45
#include < __utility/declval.h>
42
46
#include < __utility/forward.h>
43
47
#include < __utility/move.h>
48
+ #include < __utility/private_constructor_tag.h>
44
49
#include < cstddef>
50
+ #include < cstdint>
45
51
46
52
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
47
53
# pragma GCC system_header
@@ -292,6 +298,91 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
292
298
}
293
299
};
294
300
301
+ // Bounds checking in unique_ptr<T[]>
302
+ // ==================================
303
+ //
304
+ // We provide some helper classes that allow bounds checking when accessing a unique_ptr<T[]>.
305
+ // There are a few cases where bounds checking can be implemented:
306
+ //
307
+ // 1. When an array cookie (see [1]) exists at the beginning of the array allocation, we are
308
+ // able to reuse that cookie to extract the size of the array and perform bounds checking.
309
+ // An array cookie is a size inserted at the beginning of the allocation by the compiler.
310
+ // That size is inserted implicitly when doing `new T[n]` in some cases, and its purpose
311
+ // is to allow the runtime to destroy the `n` array elements when doing `delete array`.
312
+ // When we are able to use array cookies, we reuse information already available in the
313
+ // current runtime, so bounds checking does not require changing libc++'s ABI.
314
+ //
315
+ // 2. When the "bounded unique_ptr" ABI configuration (controlled by `_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`)
316
+ // is enabled, we store the size of the allocation (when it is known) so we can check it when
317
+ // indexing into the `unique_ptr`. That changes the layout of `std::unique_ptr<T[]>`, which is
318
+ // an ABI break from the default configuration.
319
+ //
320
+ // Note that even under this ABI configuration, we can't always know the size of the unique_ptr.
321
+ // Indeed, the size of the allocation can only be known when the unique_ptr is created via
322
+ // make_unique or a similar API. For example, it can't be known when constructed from an arbitrary
323
+ // pointer, in which case we are not able to check the bounds on access:
324
+ //
325
+ // unique_ptr<T[], MyDeleter> ptr(new T[3]);
326
+ //
327
+ // When we don't know the size of the allocation via the API used to create the unique_ptr, we
328
+ // try to fall back to using an array cookie when available.
329
+ //
330
+ // Finally, note that when this ABI configuration is enabled, we have no choice but to always
331
+ // make space for a size to be stored in the unique_ptr. Indeed, while we might want to avoid
332
+ // storing the size when an array cookie is available, knowing whether an array cookie is available
333
+ // requires the type stored in the unique_ptr to be complete, while unique_ptr can normally
334
+ // accommodate incomplete types.
335
+ //
336
+ // (1) Implementation where we rely on the array cookie to know the size of the allocation, if
337
+ // an array cookie exists.
338
+ struct __unique_ptr_array_bounds_stateless {
339
+ __unique_ptr_array_bounds_stateless () = default ;
340
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __unique_ptr_array_bounds_stateless (size_t ) {}
341
+
342
+ template <class _Tp , __enable_if_t <__has_array_cookie<_Tp>::value, int > = 0 >
343
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds (_Tp* __ptr, size_t __index) const {
344
+ // In constant expressions, we can't check the array cookie so we just pretend that the index
345
+ // is in-bounds. The compiler catches invalid accesses anyway.
346
+ if (__libcpp_is_constant_evaluated ())
347
+ return true ;
348
+ size_t __cookie = std::__get_array_cookie (__ptr);
349
+ return __index < __cookie;
350
+ }
351
+
352
+ template <class _Tp , __enable_if_t <!__has_array_cookie<_Tp>::value, int > = 0 >
353
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds (_Tp*, size_t ) const {
354
+ return true ; // If we don't have an array cookie, we assume the access is in-bounds
355
+ }
356
+ };
357
+
358
+ // (2) Implementation where we store the size in the class whenever we have it.
359
+ //
360
+ // Semantically, we'd need to store the size as an optional<size_t>. However, since that
361
+ // is really heavy weight, we instead store a size_t and use SIZE_MAX as a magic value
362
+ // meaning that we don't know the size.
363
+ struct __unique_ptr_array_bounds_stored {
364
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __unique_ptr_array_bounds_stored () : __size_(SIZE_MAX) {}
365
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __unique_ptr_array_bounds_stored (size_t __size) : __size_(__size) {}
366
+
367
+ // Use the array cookie if there's one
368
+ template <class _Tp , __enable_if_t <__has_array_cookie<_Tp>::value, int > = 0 >
369
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds (_Tp* __ptr, size_t __index) const {
370
+ if (__libcpp_is_constant_evaluated ())
371
+ return true ;
372
+ size_t __cookie = std::__get_array_cookie (__ptr);
373
+ return __index < __cookie;
374
+ }
375
+
376
+ // Otherwise, fall back on the stored size (if any)
377
+ template <class _Tp , __enable_if_t <!__has_array_cookie<_Tp>::value, int > = 0 >
378
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds (_Tp*, size_t __index) const {
379
+ return __index < __size_;
380
+ }
381
+
382
+ private:
383
+ size_t __size_;
384
+ };
385
+
295
386
template <class _Tp , class _Dp >
296
387
class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> {
297
388
public:
@@ -300,8 +391,9 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
300
391
typedef typename __pointer<_Tp, deleter_type>::type pointer;
301
392
302
393
// A unique_ptr contains the following members which may be trivially relocatable:
303
- // - pointer : this may be trivially relocatable, so it's checked
394
+ // - pointer: this may be trivially relocatable, so it's checked
304
395
// - deleter_type: this may be trivially relocatable, so it's checked
396
+ // - (optionally) size: this is trivially relocatable
305
397
//
306
398
// This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no
307
399
// references to itself. This means that the entire structure is trivially relocatable if its members are.
@@ -311,7 +403,16 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
311
403
void >;
312
404
313
405
private:
406
+ template <class _Up , class _OtherDeleter >
407
+ friend class unique_ptr ;
408
+
314
409
_LIBCPP_COMPRESSED_PAIR (pointer, __ptr_, deleter_type, __deleter_);
410
+ #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
411
+ using _BoundsChecker = __unique_ptr_array_bounds_stored;
412
+ #else
413
+ using _BoundsChecker = __unique_ptr_array_bounds_stateless;
414
+ #endif
415
+ _LIBCPP_NO_UNIQUE_ADDRESS _BoundsChecker __checker_;
315
416
316
417
template <class _From >
317
418
struct _CheckArrayPointerConversion : is_same<_From, pointer> {};
@@ -373,6 +474,12 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
373
474
: __ptr_(__p),
374
475
__deleter_() {}
375
476
477
+ // Private constructor used by make_unique & friends to pass the size that was allocated
478
+ template <class _Tag , class _Ptr , __enable_if_t <is_same<_Tag, __private_constructor_tag>::value, int > = 0 >
479
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr (_Tag, _Ptr __ptr, size_t __size) _NOEXCEPT
480
+ : __ptr_(__ptr),
481
+ __checker_(__size) {}
482
+
376
483
template <class _Pp ,
377
484
bool _Dummy = true ,
378
485
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
@@ -411,11 +518,13 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
411
518
412
519
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr (unique_ptr&& __u) _NOEXCEPT
413
520
: __ptr_(__u.release()),
414
- __deleter_(std::forward<deleter_type>(__u.get_deleter())) {}
521
+ __deleter_(std::forward<deleter_type>(__u.get_deleter())),
522
+ __checker_(std::move(__u.__checker_)) {}
415
523
416
524
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator =(unique_ptr&& __u) _NOEXCEPT {
417
525
reset (__u.release ());
418
526
__deleter_ = std::forward<deleter_type>(__u.get_deleter ());
527
+ __checker_ = std::move (std::move (__u.__checker_ ));
419
528
return *this ;
420
529
}
421
530
@@ -425,7 +534,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
425
534
class = _EnableIfDeleterConvertible<_Ep> >
426
535
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr (unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
427
536
: __ptr_(__u.release()),
428
- __deleter_(std::forward<_Ep>(__u.get_deleter())) {}
537
+ __deleter_(std::forward<_Ep>(__u.get_deleter())),
538
+ __checker_(std::move(__u.__checker_)) {}
429
539
430
540
template <class _Up ,
431
541
class _Ep ,
@@ -434,6 +544,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
434
544
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator =(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
435
545
reset (__u.release ());
436
546
__deleter_ = std::forward<_Ep>(__u.get_deleter ());
547
+ __checker_ = std::move (__u.__checker_ );
437
548
return *this ;
438
549
}
439
550
@@ -451,6 +562,8 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
451
562
}
452
563
453
564
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t <_Tp> operator [](size_t __i) const {
565
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (__checker_.__in_bounds (std::__to_address (__ptr_), __i),
566
+ " unique_ptr<T[]>::operator[](index): index out of range" );
454
567
return __ptr_[__i];
455
568
}
456
569
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get () const _NOEXCEPT { return __ptr_; }
@@ -467,20 +580,24 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
467
580
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release () _NOEXCEPT {
468
581
pointer __t = __ptr_;
469
582
__ptr_ = pointer ();
583
+ // The deleter and the optional bounds-checker are left unchanged. The bounds-checker
584
+ // will be reinitialized appropriately when/if the unique_ptr gets assigned-to or reset.
470
585
return __t ;
471
586
}
472
587
473
588
template <class _Pp , __enable_if_t <_CheckArrayPointerConversion<_Pp>::value, int > = 0 >
474
589
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset (_Pp __p) _NOEXCEPT {
475
590
pointer __tmp = __ptr_;
476
591
__ptr_ = __p;
592
+ __checker_ = _BoundsChecker ();
477
593
if (__tmp)
478
594
__deleter_ (__tmp);
479
595
}
480
596
481
597
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset (nullptr_t = nullptr ) _NOEXCEPT {
482
598
pointer __tmp = __ptr_;
483
599
__ptr_ = nullptr ;
600
+ __checker_ = _BoundsChecker ();
484
601
if (__tmp)
485
602
__deleter_ (__tmp);
486
603
}
@@ -489,6 +606,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
489
606
using std::swap;
490
607
swap (__ptr_, __u.__ptr_ );
491
608
swap (__deleter_, __u.__deleter_ );
609
+ swap (__checker_, __u.__checker_ );
492
610
}
493
611
};
494
612
@@ -645,7 +763,7 @@ template <class _Tp>
645
763
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound
646
764
make_unique (size_t __n) {
647
765
typedef __remove_extent_t <_Tp> _Up;
648
- return unique_ptr<_Tp>(new _Up[__n]());
766
+ return unique_ptr<_Tp>(__private_constructor_tag (), new _Up[__n](), __n );
649
767
}
650
768
651
769
template <class _Tp , class ... _Args>
@@ -664,7 +782,7 @@ make_unique_for_overwrite() {
664
782
template <class _Tp >
665
783
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound
666
784
make_unique_for_overwrite (size_t __n) {
667
- return unique_ptr<_Tp>(new __remove_extent_t <_Tp>[__n]);
785
+ return unique_ptr<_Tp>(__private_constructor_tag (), new __remove_extent_t <_Tp>[__n], __n );
668
786
}
669
787
670
788
template <class _Tp , class ... _Args>
0 commit comments