lazy_split_view
, comparing a default-constructed outer-iterator
or
inner-iterator
with std::default_sentinel
results in null pointer dereferenceSection: 25.7.16.3 [range.lazy.split.outer], 25.7.16.5 [range.lazy.split.inner] Status: New Submitter: Konstantin Varlamov Opened: 2022-03-23 Last modified: 2022-05-17
Priority: 3
View all other issues in [range.lazy.split.outer].
View all issues with New status.
Discussion:
The internal iterator types outer-iterator
and inner-iterator
of
lazy_split_view
are default-constructible, but trying to compare a default-constructed
instance of either of these classes to std::default_sentinel
results in null pointer
dereference (and, in all likelihood, a crash), as demonstrated in this
demo link:
// AssumingOuterIter
is an alias forouter-iterator
of // somelazy_split_view
instantiation. OuterIter o; o == std::default_sentinel; // Null pointer dereference InnerIter i; // Similar toOuterIter
above. i == std::default_sentinel; // Null pointer dereference
This is due to unchecked pointer access in the implementation of outer-iterator
(25.7.16.3 [range.lazy.split.outer] p8):
return x.current == ranges::end(x.parent_->base_) && !x.trailing_empty_;
(parent_
is null for a default-constructed iterator x
, making the access
to base_
invalid)
inner-iterator
(25.7.16.5 [range.lazy.split.inner] p7):
auto [pcur, pend] = subrange{x.i_.parent_->pattern_};
(For a default-constructed inner-iterator x
, i_
is a default-constructed
outer-iterator
member variable and i_.parent_
is null, making the
access to pattern_
invalid)
std::default_sentinel
to be a well-defined operation that returns true
. Alternatively,
the corresponding operator==
functions should add a non-normative note stating that the
iterator cannot be default-constructed.
[2022-05-17; Reflector poll]
Set priority to 3 after reflector poll. Three votes for NAD.
Proposed resolution:
This wording is relative to N4910.
Modify 25.7.16.3 [range.lazy.split.outer] as indicated:
friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);-8- Effects: Equivalent to:
if (!x.parent_) return true; return x.current == ranges::end(x.parent_->base_) && !x.trailing_empty_;
Modify 25.7.16.5 [range.lazy.split.inner], as indicated:
friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);-7- Effects: Equivalent to:
if (!x.i_.parent_) return true; auto [pcur, pend] = subrange{x.i_.parent_->pattern_}; […]