[libcxx-commits] [libcxx] dfe737f - [libc++] Apply post-commit review comments for unique_ptr<T[]> hardening (#111704)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Nov 4 07:45:15 PST 2024


Author: Louis Dionne
Date: 2024-11-04T10:45:12-05:00
New Revision: dfe737f231d7162ea5658df3b97fd71cc39441d8

URL: https://github.com/llvm/llvm-project/commit/dfe737f231d7162ea5658df3b97fd71cc39441d8
DIFF: https://github.com/llvm/llvm-project/commit/dfe737f231d7162ea5658df3b97fd71cc39441d8.diff

LOG: [libc++] Apply post-commit review comments for unique_ptr<T[]> hardening (#111704)

Added: 
    

Modified: 
    libcxx/docs/Hardening.rst
    libcxx/docs/ReleaseNotes/20.rst
    libcxx/include/__configuration/abi.h
    libcxx/include/__memory/unique_ptr.h
    libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/incomplete.sh.cpp
    libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Hardening.rst b/libcxx/docs/Hardening.rst
index 67791a5e55ac7c..fd0f3af5ef2f96 100644
--- a/libcxx/docs/Hardening.rst
+++ b/libcxx/docs/Hardening.rst
@@ -341,6 +341,16 @@ Vendors can use the following ABI options to enable additional hardening checks:
 
   ABI impact: changes the iterator type of ``vector`` (except ``vector<bool>``).
 
+- ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR``` -- tracks the bounds of the array stored inside
+  a ``std::unique_ptr<T[]>``, allowing it to trap when accessed out-of-bounds. This
+  requires the ``std::unique_ptr`` to be created using an API like ``std::make_unique``
+  or ``std::make_unique_for_overwrite``, otherwise the bounds information is not available
+  to the library.
+
+  ABI impact: changes the layout of ``std::unique_ptr<T[]>``, and the representation
+              of a few library types that use ``std::unique_ptr`` internally, such as
+              the unordered containers.
+
 ABI tags
 --------
 

diff  --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index bf3aafe6139ee9..905fd81cd6faab 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -62,6 +62,10 @@ Improvements and New Features
   compile times and smaller debug information as well as better code generation if optimizations are disabled.
   The Chromium project measured a 5% reduction in object file and debug information size.
 
+- The ``_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`` ABI configuration was added, which allows ``std::unique_ptr<T[]>`` to
+  detect out-of-bounds accesses in certain circumstances. ``std::unique_ptr<T[]>`` can now also detect out-of-bounds
+  accesses for a limited set of types (non-trivially destructible types) when the ABI configuration is disabled.
+
 Deprecations and Removals
 -------------------------
 

diff  --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 62c129f5921dee..7095d56c6dc39d 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -186,6 +186,8 @@
 // of types can be checked.
 //
 // ABI impact: This causes the layout of std::unique_ptr<T[]> to change and its size to increase.
+//             This also affects the representation of a few library types that use std::unique_ptr
+//             internally, such as the unordered containers.
 // #define _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
 
 #if defined(_LIBCPP_COMPILER_CLANG_BASED)

diff  --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index 6203ec74fa8fd1..28c62e13566e24 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -546,7 +546,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
     reset(__u.release());
     __deleter_ = std::forward<deleter_type>(__u.get_deleter());
-    __checker_ = std::move(std::move(__u.__checker_));
+    __checker_ = std::move(__u.__checker_);
     return *this;
   }
 

diff  --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/incomplete.sh.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/incomplete.sh.cpp
index 4a03d2bcf07bfe..f208e0cb3737d2 100644
--- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/incomplete.sh.cpp
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/incomplete.sh.cpp
@@ -23,19 +23,19 @@
 #include <memory>
 #include <cassert>
 
-struct T;
-extern void use(std::unique_ptr<T>& ptr);
-extern void use(std::unique_ptr<T[]>& ptr);
+struct Foo;
+extern void use(std::unique_ptr<Foo>& ptr);
+extern void use(std::unique_ptr<Foo[]>& ptr);
 
 #ifdef INCOMPLETE
 
-void use(std::unique_ptr<T>& ptr) {
+void use(std::unique_ptr<Foo>& ptr) {
   {
-    T* x = ptr.get();
+    Foo* x = ptr.get();
     assert(x != nullptr);
   }
   {
-    T& ref = *ptr;
+    Foo& ref = *ptr;
     assert(&ref == ptr.get());
   }
   {
@@ -52,9 +52,9 @@ void use(std::unique_ptr<T>& ptr) {
   }
 }
 
-void use(std::unique_ptr<T[]>& ptr) {
+void use(std::unique_ptr<Foo[]>& ptr) {
   {
-    T* x = ptr.get();
+    Foo* x = ptr.get();
     assert(x != nullptr);
   }
   {
@@ -75,16 +75,16 @@ void use(std::unique_ptr<T[]>& ptr) {
 
 #ifdef COMPLETE
 
-struct T {}; // complete the type
+struct Foo {}; // complete the type
 
 int main(int, char**) {
   {
-    std::unique_ptr<T> ptr(new T());
+    std::unique_ptr<Foo> ptr(new Foo());
     use(ptr);
   }
 
   {
-    std::unique_ptr<T[]> ptr(new T[3]());
+    std::unique_ptr<Foo[]> ptr(new Foo[3]());
     use(ptr);
   }
   return 0;

diff  --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp
index bb4ac981600f9e..b7cc12350027b9 100644
--- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.observers/assert.subscript.pass.cpp
@@ -26,6 +26,7 @@
 
 #include "check_assertion.h"
 #include "type_algorithms.h"
+#include "test_macros.h"
 
 struct MyDeleter {
   MyDeleter() = default;
@@ -48,6 +49,9 @@ struct MyDeleter {
 
 template <class WithCookie, class NoCookie>
 void test() {
+  LIBCPP_STATIC_ASSERT(std::__has_array_cookie<WithCookie>::value);
+  LIBCPP_STATIC_ASSERT(!std::__has_array_cookie<NoCookie>::value);
+
   // For types with an array cookie, we can always detect OOB accesses. Note that reliance on an array
   // cookie is limited to the default deleter, since a unique_ptr with a custom deleter may not have
   // been allocated with `new T[n]`.


        


More information about the libcxx-commits mailing list