Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Indexing operator of iterator_range<counting_iterator<...>> produces undefined behavior #83

Open
mkatliar opened this issue Nov 23, 2018 · 2 comments

Comments

@mkatliar
Copy link

mkatliar commented Nov 23, 2018

Example:

#include <boost/iterator/counting_iterator.hpp>
#include <boost/range/iterator_range.hpp>

#include <iostream>
#include <type_traits>

int main(int, char **)
{
    using iterator = boost::counting_iterator<int>;
    using iterator_range = boost::iterator_range<iterator>;

    iterator first(0), last(3);
    iterator_range range(first, last);

    std::cout << "iterator::reference is a reference type: " << std::is_reference<iterator::reference>::value << std::endl;
    std::cout << "iterator_range::reference is a reference type: " << std::is_reference<iterator_range::reference>::value << std::endl;

    std::cout << "first[0] returns a reference type: " << std::is_reference<decltype(first[0])>::value << std::endl;
    std::cout << "range[0] returns a reference type: " << std::is_reference<decltype(range[0])>::value << std::endl;
    
    std::cout << "first[0] == " << first[0] << std::endl;
    std::cout << "range[0] == " << range[0] << std::endl; // <-- segfault
}

Output:

iterator::reference is a reference type: 1
iterator_range::reference is a reference type: 1
first[0] returns a reference type: 0
range[0] returns a reference type: 1
first[0] == 0
Segmentation fault (core dumped)

Expected behavior: range[0] returns 0.

If Boost headers are copied to ./boost and the program is compiled with g++ -I. option, the compiler produces the following warning:

In file included from ./boost/range/iterator_range.hpp:13,
                 from test_counting_iterator_range_indexing.cpp:2:
./boost/range/iterator_range_core.hpp: In instantiation of ‘boost::iterator_range_detail::iterator_range_base<IteratorT, boost::iterators::random_access_traversal_tag>::reference boost::iterator_range_detail::iterator_range_base<IteratorT, boost::iterators::random_access_traversal_tag>::operator[](boost::iterator_range_detail::iterator_range_base<IteratorT, boost::iterators::random_access_traversal_tag>::difference_type) const [with IteratorT = boost::iterators::counting_iterator<int>; boost::iterator_range_detail::iterator_range_base<IteratorT, boost::iterators::random_access_traversal_tag>::reference = const int&; boost::iterator_range_detail::iterator_range_base<IteratorT, boost::iterators::random_access_traversal_tag>::difference_type = long int]’:
test_counting_iterator_range_indexing.cpp:23:43:   required from here
./boost/range/iterator_range_core.hpp:391:32: warning: returning reference to temporary [-Wreturn-local-addr]
         return this->m_Begin[at];
                                ^

The reason for the segmentation fault is that iterator_range::operator[] returns a reference to a stack-allocated object returned by counting_iterator::operator[].

@jeremy-murphy
Copy link

What happens if you try the same test with counting_range from Boost.Range?

@morinmorin
Copy link
Member

Please don't use counting_iterator/counting_range. Use irange(0, 3), instead.

detu pushed a commit to detu/tmpc that referenced this issue Jun 12, 2022
…est_ocpGraphFromOutDegree in Release builds. See boostorg/range#83 for more details.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants