Opened 8 years ago
Last modified 5 years ago
#10493 assigned Bugs
Since 1.56, any_range with non-reference references can cause UB
Reported by: | Owned by: | Neil Groves | |
---|---|---|---|
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; }
Change History (8)
comment:1 by , 8 years ago
Cc: | added |
---|
comment:2 by , 8 years ago
Milestone: | To Be Determined → Boost 1.58.0 |
---|---|
Status: | new → assigned |
comment:3 by , 7 years ago
comment:5 by , 7 years ago
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 by , 6 years ago
Milestone: | Boost 1.58.0 → Boost 1.64.0 |
---|---|
Version: | Boost 1.56.0 → Boost 1.62.0 |
Problem still exists boost 1.62
comment:7 by , 5 years ago
Still have this bug in 1.64. Adding const
to Reference
works around the problem but disables move construction. Is there any other workaround?
comment:8 by , 5 years ago
Problem still there in boost 1.65.1
Adding const to Reference doesn't workaround the problem (at least on Visual Studio): c:\path\to\boost\1.65.1\include\boost\range\detail\any_iterator_wrapper.hpp(302) : warning C4172: returning address of local variable or temporary
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
I haven't digged into any_iterator sources but seems it behave differently when Reference is const