[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