Skip to content

Commit dfe737f

Browse files
authored
[libc++] Apply post-commit review comments for unique_ptr<T[]> hardening (#111704)
1 parent 0713bf9 commit dfe737f

File tree

6 files changed

+32
-12
lines changed

6 files changed

+32
-12
lines changed

libcxx/docs/Hardening.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,16 @@ Vendors can use the following ABI options to enable additional hardening checks:
341341

342342
ABI impact: changes the iterator type of ``vector`` (except ``vector<bool>``).
343343

344+
- ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR``` -- tracks the bounds of the array stored inside
345+
a ``std::unique_ptr<T[]>``, allowing it to trap when accessed out-of-bounds. This
346+
requires the ``std::unique_ptr`` to be created using an API like ``std::make_unique``
347+
or ``std::make_unique_for_overwrite``, otherwise the bounds information is not available
348+
to the library.
349+
350+
ABI impact: changes the layout of ``std::unique_ptr<T[]>``, and the representation
351+
of a few library types that use ``std::unique_ptr`` internally, such as
352+
the unordered containers.
353+
344354
ABI tags
345355
--------
346356

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ Improvements and New Features
6262
compile times and smaller debug information as well as better code generation if optimizations are disabled.
6363
The Chromium project measured a 5% reduction in object file and debug information size.
6464

65+
- The ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`` ABI configuration was added, which allows ``std::unique_ptr<T[]>`` to
66+
detect out-of-bounds accesses in certain circumstances. ``std::unique_ptr<T[]>`` can now also detect out-of-bounds
67+
accesses for a limited set of types (non-trivially destructible types) when the ABI configuration is disabled.
68+
6569
Deprecations and Removals
6670
-------------------------
6771

libcxx/include/__configuration/abi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@
186186
// of types can be checked.
187187
//
188188
// ABI impact: This causes the layout of std::unique_ptr<T[]> to change and its size to increase.
189+
// This also affects the representation of a few library types that use std::unique_ptr
190+
// internally, such as the unordered containers.
189191
// #define _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
190192

191193
#if defined(_LIBCPP_COMPILER_CLANG_BASED)

libcxx/include/__memory/unique_ptr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
546546
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
547547
reset(__u.release());
548548
__deleter_ = std::forward<deleter_type>(__u.get_deleter());
549-
__checker_ = std::move(std::move(__u.__checker_));
549+
__checker_ = std::move(__u.__checker_);
550550
return *this;
551551
}
552552

libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/incomplete.sh.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@
2323
#include <memory>
2424
#include <cassert>
2525

26-
struct T;
27-
extern void use(std::unique_ptr<T>& ptr);
28-
extern void use(std::unique_ptr<T[]>& ptr);
26+
struct Foo;
27+
extern void use(std::unique_ptr<Foo>& ptr);
28+
extern void use(std::unique_ptr<Foo[]>& ptr);
2929

3030
#ifdef INCOMPLETE
3131

32-
void use(std::unique_ptr<T>& ptr) {
32+
void use(std::unique_ptr<Foo>& ptr) {
3333
{
34-
T* x = ptr.get();
34+
Foo* x = ptr.get();
3535
assert(x != nullptr);
3636
}
3737
{
38-
T& ref = *ptr;
38+
Foo& ref = *ptr;
3939
assert(&ref == ptr.get());
4040
}
4141
{
@@ -52,9 +52,9 @@ void use(std::unique_ptr<T>& ptr) {
5252
}
5353
}
5454

55-
void use(std::unique_ptr<T[]>& ptr) {
55+
void use(std::unique_ptr<Foo[]>& ptr) {
5656
{
57-
T* x = ptr.get();
57+
Foo* x = ptr.get();
5858
assert(x != nullptr);
5959
}
6060
{
@@ -75,16 +75,16 @@ void use(std::unique_ptr<T[]>& ptr) {
7575

7676
#ifdef COMPLETE
7777

78-
struct T {}; // complete the type
78+
struct Foo {}; // complete the type
7979

8080
int main(int, char**) {
8181
{
82-
std::unique_ptr<T> ptr(new T());
82+
std::unique_ptr<Foo> ptr(new Foo());
8383
use(ptr);
8484
}
8585

8686
{
87-
std::unique_ptr<T[]> ptr(new T[3]());
87+
std::unique_ptr<Foo[]> ptr(new Foo[3]());
8888
use(ptr);
8989
}
9090
return 0;

libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include "check_assertion.h"
2828
#include "type_algorithms.h"
29+
#include "test_macros.h"
2930

3031
struct MyDeleter {
3132
MyDeleter() = default;
@@ -48,6 +49,9 @@ struct MyDeleter {
4849

4950
template <class WithCookie, class NoCookie>
5051
void test() {
52+
LIBCPP_STATIC_ASSERT(std::__has_array_cookie<WithCookie>::value);
53+
LIBCPP_STATIC_ASSERT(!std::__has_array_cookie<NoCookie>::value);
54+
5155
// For types with an array cookie, we can always detect OOB accesses. Note that reliance on an array
5256
// cookie is limited to the default deleter, since a unique_ptr with a custom deleter may not have
5357
// been allocated with `new T[n]`.

0 commit comments

Comments
 (0)