Skip to content

Commit 5174b38

Browse files
authored
[libc++] Use __wrap_iter in string_view and array in the unstable ABI (#74482)
std::string_view and std::array iterators don't have to be raw pointers, and in fact other implementations don't represent them as raw pointers. Them being raw pointers in libc++ makes it easier for users to write non-portable code. This is bad in itself, but this is even worse when considering efforts like hardening where we want an easy ability to swap for a different iterator type. If users depend on iterators being raw pointers, this becomes a build break. Hence, this patch enables the use of __wrap_iter in the unstable ABI, creating a long term path towards making this the default. This patch may break code that assumes these iterators are raw pointers for people compiling with the unstable ABI. This patch also removes several assumptions that array iterators are raw pointers in the code base and in the test suite.
1 parent 4d80df0 commit 5174b38

File tree

4 files changed

+31
-12
lines changed

4 files changed

+31
-12
lines changed

libcxx/include/__config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@
174174
// The implementation moved to the header, but we still export the symbols from
175175
// the dylib for backwards compatibility.
176176
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
177+
// Define std::array/std::string_view iterators to be __wrap_iters instead of raw
178+
// pointers, which prevents people from relying on a non-portable implementation
179+
// detail. This is especially useful because enabling bounded iterators hardening
180+
// requires code not to make these assumptions.
181+
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
182+
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
177183
# elif _LIBCPP_ABI_VERSION == 1
178184
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
179185
// Enable compiling copies of now inline methods into the dylib to support

libcxx/include/__iterator/wrap_iter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,14 @@ class __wrap_iter {
9797
friend class __wrap_iter;
9898
template <class _CharT, class _Traits, class _Alloc>
9999
friend class basic_string;
100+
template <class _CharT, class _Traits>
101+
friend class basic_string_view;
100102
template <class _Tp, class _Alloc>
101103
friend class _LIBCPP_TEMPLATE_VIS vector;
102104
template <class _Tp, size_t>
103105
friend class _LIBCPP_TEMPLATE_VIS span;
106+
template <class _Tp, size_t _Size>
107+
friend struct array;
104108
};
105109

106110
template <class _Iter1>

libcxx/include/array

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
120120
#include <__config>
121121
#include <__fwd/array.h>
122122
#include <__iterator/reverse_iterator.h>
123+
#include <__iterator/wrap_iter.h>
123124
#include <__tuple/sfinae_helpers.h>
124125
#include <__type_traits/conditional.h>
125126
#include <__type_traits/is_array.h>
@@ -167,14 +168,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
167168
template <class _Tp, size_t _Size>
168169
struct _LIBCPP_TEMPLATE_VIS array {
169170
// types:
170-
using __self = array;
171-
using value_type = _Tp;
172-
using reference = value_type&;
173-
using const_reference = const value_type&;
174-
using iterator = value_type*;
175-
using const_iterator = const value_type*;
176-
using pointer = value_type*;
177-
using const_pointer = const value_type*;
171+
using __self = array;
172+
using value_type = _Tp;
173+
using reference = value_type&;
174+
using const_reference = const value_type&;
175+
using pointer = value_type*;
176+
using const_pointer = const value_type*;
177+
#if defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY)
178+
using iterator = __wrap_iter<pointer>;
179+
using const_iterator = __wrap_iter<const_pointer>;
180+
#else
181+
using iterator = pointer;
182+
using const_iterator = const_pointer;
183+
#endif
178184
using size_type = size_t;
179185
using difference_type = ptrdiff_t;
180186
using reverse_iterator = std::reverse_iterator<iterator>;

libcxx/include/string_view

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ namespace std {
215215
#include <__iterator/concepts.h>
216216
#include <__iterator/iterator_traits.h>
217217
#include <__iterator/reverse_iterator.h>
218+
#include <__iterator/wrap_iter.h>
218219
#include <__memory/pointer_traits.h>
219220
#include <__ranges/concepts.h>
220221
#include <__ranges/data.h>
@@ -278,10 +279,12 @@ public:
278279
using const_pointer = const _CharT*;
279280
using reference = _CharT&;
280281
using const_reference = const _CharT&;
281-
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
282+
#if defined(_LIBCPP_ABI_BOUNDED_ITERATORS)
282283
using const_iterator = __bounded_iter<const_pointer>;
284+
#elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW)
285+
using const_iterator = __wrap_iter<const_pointer>;
283286
#else
284-
using const_iterator = const_pointer; // See [string.view.iterators]
287+
using const_iterator = const_pointer;
285288
#endif
286289
using iterator = const_iterator;
287290
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@@ -353,15 +356,15 @@ public:
353356
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
354357
return std::__make_bounded_iter(data(), data(), data() + size());
355358
#else
356-
return __data_;
359+
return const_iterator(__data_);
357360
#endif
358361
}
359362

360363
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT {
361364
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
362365
return std::__make_bounded_iter(data() + size(), data(), data() + size());
363366
#else
364-
return __data_ + __size_;
367+
return const_iterator(__data_ + __size_);
365368
#endif
366369
}
367370

0 commit comments

Comments
 (0)