[libcxx-commits] [libcxx] [libc++] Crash when dereferencing an empty std::optional (PR #116394)
Andrej Shadura via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Nov 15 07:10:13 PST 2024
https://github.com/andrewshadura created https://github.com/llvm/llvm-project/pull/116394
Dereferencing a std::optional that does not contain a value is undefined behaviour. It is better to crash when this happens to prevent potential abuse or a crash further down the line.
[reworded the commit message]
Co-Authored-By: Andrej Shadura <andrew.shadura at collabora.co.uk>
>From c4ae884a0bbeb65a23706f4d13d22d32fed6ecc6 Mon Sep 17 00:00:00 2001
From: Grace Cham <hscham at chromium.org>
Date: Tue, 16 Jul 2024 23:17:37 +0000
Subject: [PATCH] [libc++] Crash when dereferencing an empty std::optional
Dereferencing a std::optional that does not contain a value is
undefined behaviour. It is better to crash when this happens to
prevent potential abuse or a crash further down the line.
[reworded the commit message]
Co-Authored-By: Andrej Shadura <andrew.shadura at collabora.co.uk>
---
libcxx/include/optional | 38 ++++++++++++++++++++++++++++++++------
1 file changed, 32 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 7ad6a9e116941f..71c0eabed446dc 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -177,6 +177,8 @@ namespace std {
*/
+#include <stdio.h>
+
#include <__assert>
#include <__compare/compare_three_way_result.h>
#include <__compare/ordering.h>
@@ -791,33 +793,57 @@ public:
}
}
- _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type const> operator->() const noexcept {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr add_pointer_t<value_type const> operator->() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
+ if (!this->has_value()) {
+ fprintf(stderr, "optional operator-> called on a disengaged value\n");
+ __builtin_trap();
+ }
return std::addressof(this->__get());
}
- _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<value_type> operator->() noexcept {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr add_pointer_t<value_type> operator->() noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
+ if (!this->has_value()) {
+ fprintf(stderr, "optional operator-> called on a disengaged value\n");
+ __builtin_trap();
+ }
return std::addressof(this->__get());
}
- _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr const value_type& operator*() const& noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
+ if (!this->has_value()) {
+ fprintf(stderr, "optional operator-> called on a disengaged value\n");
+ __builtin_trap();
+ }
return this->__get();
}
- _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& operator*() & noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
+ if (!this->has_value()) {
+ fprintf(stderr, "optional operator-> called on a disengaged value\n");
+ __builtin_trap();
+ }
return this->__get();
}
- _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& operator*() && noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
+ if (!this->has_value()) {
+ fprintf(stderr, "optional operator-> called on a disengaged value\n");
+ __builtin_trap();
+ }
return std::move(this->__get());
}
- _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr const value_type&& operator*() const&& noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
+ if (!this->has_value()) {
+ fprintf(stderr, "optional operator-> called on a disengaged value\n");
+ __builtin_trap();
+ }
return std::move(this->__get());
}
More information about the libcxx-commits
mailing list