[libcxx-commits] [libcxx] [libcxx] adds additional checks to RAI containers' `erase` (PR #90919)
Christopher Di Bella via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jun 10 10:08:02 PDT 2024
https://github.com/cjdb updated https://github.com/llvm/llvm-project/pull/90919
>From d642ffee047dc5ee6a1ff1a37ee1d0913b5fd5e4 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 2 May 2024 23:56:48 +0000
Subject: [PATCH 1/2] [libcxx] adds additional checks to RAI containers'
`erase`
This ensures that the iterators passed in are in-range for the
container. Thanks to @mclow for identifying this opportunity.
---
libcxx/include/deque | 11 +++++++++--
libcxx/include/string | 11 +++++++++--
libcxx/include/vector | 11 +++++++++--
3 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 3c33e04e9f05f..2df644cd3d80e 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -2372,7 +2372,9 @@ void deque<_Tp, _Allocator>::__move_construct_backward_and_check(
template <class _Tp, class _Allocator>
typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
- __f != end(), "deque::erase(iterator) called with a non-dereferenceable iterator");
+ __f >= begin(), "deque::erase(iterator) called with an iterator outside of the container's control");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __f < end(), "deque::erase(iterator) called with an iterator outside of the container's control");
size_type __old_sz = size();
size_type __old_start = __start_;
iterator __b = begin();
@@ -2398,7 +2400,12 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_it
template <class _Tp, class _Allocator>
typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) {
- _LIBCPP_ASSERT_VALID_INPUT_RANGE(__f <= __l, "deque::erase(first, last) called with an invalid range");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __f <= begin(), "deque::erase(first, last) called with an iterator range starting before 'begin()'");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __l <= end(), "deque::erase(first, last) called with an iterator range finishing after 'end()'");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __f <= __l, "deque::erase(first, last) called with an invalid range");
size_type __old_sz = size();
size_type __old_start = __start_;
difference_type __n = __l - __f;
diff --git a/libcxx/include/string b/libcxx/include/string
index 4e3dd278c12b0..3f15e0b766edd 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -3155,7 +3155,9 @@ template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
- __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator");
+ __pos >= begin(), "string::erase(iterator) called with an iterator outside of the container's control");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __pos < end(), "string::erase(iterator) called with an iterator outside of the container's control");
iterator __b = begin();
size_type __r = static_cast<size_type>(__pos - __b);
erase(__r, 1);
@@ -3165,7 +3167,12 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) {
template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator
basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) {
- _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __first >= begin(), "string::erase(first, last) called with an iterator range starting before 'begin()'");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __last <= end(), "string::erase(first, last) called with an iterator range finishing after 'end()'");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __first <= __last, "string::erase(first, last) called with invalid range");
iterator __b = begin();
size_type __r = static_cast<size_type>(__first - __b);
erase(__r, static_cast<size_type>(__last - __first));
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 976bde9b9048c..16cb3bab942dd 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -1537,7 +1537,9 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
- __position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
+ __position >= begin(), "vector::erase(iterator) called with an iterator outside of the container's control");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __position < end(), "vector::erase(iterator) called with an iterator outside of the container's control");
difference_type __ps = __position - cbegin();
pointer __p = this->__begin_ + __ps;
this->__destruct_at_end(std::move(__p + 1, this->__end_, __p));
@@ -1547,7 +1549,12 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
- _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __first >= begin(), "vector::erase(first, last) called with an iterator range starting before 'begin()'");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __last <= end(), "vector::erase(first, last) called with an iterator range finishing after 'end()'");
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __first <= __last, "vector::erase(first, last) called with invalid range");
pointer __p = this->__begin_ + (__first - begin());
if (__first != __last) {
this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p));
>From 4f36eb47800ee0dd7fe96092849c606be8370ed9 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb.ns at gmail.com>
Date: Mon, 10 Jun 2024 10:07:55 -0700
Subject: [PATCH 2/2] Update libcxx/include/deque
Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>
---
libcxx/include/deque | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/deque b/libcxx/include/deque
index 2df644cd3d80e..232285c84724b 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -2401,7 +2401,7 @@ typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_it
template <class _Tp, class _Allocator>
typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
- __f <= begin(), "deque::erase(first, last) called with an iterator range starting before 'begin()'");
+ __f >= begin(), "deque::erase(first, last) called with an iterator range starting before 'begin()'");
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
__l <= end(), "deque::erase(first, last) called with an iterator range finishing after 'end()'");
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
More information about the libcxx-commits
mailing list