Modify

Opened 3 years ago

Last modified 5 months ago

#10493 assigned Bugs

Since 1.56, any_range with non-reference references can cause UB

Reported by: nofitserov@… Owned by: neilgroves
Milestone: Boost 1.64.0 Component: range
Version: Boost 1.62.0 Severity: Regression
Keywords: Cc: p.omta@…

Description

This must be related to #10360. This is a regression since 1.55.

When using any_range<T, category, T, ptrdiff_t>, mutable dereference() method returns mutable_reference_type_generator<T>::type, which becomes T&. So dereference() returns a dangling reference to an on-the-fly computed value.

See attached test case, which works with 1.55, and fails with -fsanitize=address on Clang 3.5 with 1.56.

#include <boost/range/any_range.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <cmath>
#include <iostream>

typedef boost::any_range<
    std::string,
    boost::forward_traversal_tag,
    std::string,
    std::ptrdiff_t
> range_t;

std::string f(std::string a)
{
    return a + "!";
}

int main()
{
    std::vector<std::string> v = {"a", "b"};
    range_t r = v | boost::adaptors::transformed(f);
    for (auto&& a : r)
        std::cout << a << std::endl;
    return 0;
}

Attachments (0)

Change History (6)

comment:1 Changed 3 years ago by Paul Omta <p.omta@…>

  • Cc p.omta@… added

comment:2 Changed 2 years ago by neilgroves

  • Milestone changed from To Be Determined to Boost 1.58.0
  • Status changed from new to assigned

comment:3 Changed 2 years ago by anonymous

Just reproduced it with boost 1.58 after migration from 1.55. I tried to play with it and found how to make it work.

Using const std::string instead of std::string, seems fix the problem

typedef boost::any_range<
    std::string,
    boost::forward_traversal_tag,
    const std::string,
    std::ptrdiff_t
> range_t;

I haven't digged into any_iterator sources but seems it behave differently when Reference is const

comment:4 Changed 2 years ago by kozlov.taras@…

Forget to add email in previous comment

comment:5 Changed 22 months ago by Tobias Reh <treh@…>

Still present in 1.59.0

The problem is becoming more visible with MSVC++2015 because the compiler is better in detecting dangling references and emitting errors for them. To hard code those checks, just add the following assert into every dereference() method in range/detail/any_iterator_wrapper.hpp:

static_assert(
   !std::is_lvalue_reference<reference>::value 
   || std::is_lvalue_reference<decltype(*m_it)>::value,
   "dangling ref"
);

A little bit of digging in the headers shows that the problem lies in range/detail/any_iterator_interface.hpp, where any_incrementable_iterator_interface's

typedef Reference reference;

was changed in 1.56.0 to

typedef typename mutable_reference_type_generator<
    Reference
>::type reference;

Rolling this back solves the problem for our codebase. Any possibilities of having this fixed soon?

comment:6 Changed 5 months ago by wslcdg@…

  • Milestone changed from Boost 1.58.0 to Boost 1.64.0
  • Version changed from Boost 1.56.0 to Boost 1.62.0

Problem still exists boost 1.62

Add Comment

Modify Ticket

Change Properties
Set your email in Preferences
Action
as assigned The owner will remain neilgroves.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.