[Boost-bugs] [Boost C++ Libraries] #9578: Adapters (map_keys, map_values) cause undefined behavior (segv, etc) when applied to R-Values, especially in the context of BOOST_FOREACH

Subject: [Boost-bugs] [Boost C++ Libraries] #9578: Adapters (map_keys, map_values) cause undefined behavior (segv, etc) when applied to R-Values, especially in the context of BOOST_FOREACH
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2014-01-15 20:36:28


#9578: Adapters (map_keys, map_values) cause undefined behavior (segv, etc) when
applied to R-Values, especially in the context of BOOST_FOREACH
----------------------------------------+-------------------------
 Reporter: Igor Lubashev <ilubashe@…> | Owner: neilgroves
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: range
  Version: Boost 1.55.0 | Severity: Showstopper
 Keywords: |
----------------------------------------+-------------------------
 When applied to r-values (for example, maps returned by value from a
 function), adapters do not make a copy of the r-value but just capture a
 reference to it. This makes the returned range_iterator dangerous, if it
 is used after the r-value (the temporary) is destroyed.

 In particular, the following use causes undefined behavior on all
 compilers I'd tested on: g++ (4.1.2, 4.4.3, 4.6.3) and Visual Studio (15
 [VC9], 16 [VC10]).

 {{{
 #!cpp
 BOOST_FOREACH(const string &s, return_map_by_value() | map_keys)
   ...
 }}}

 Note that the following works fine (since BOOST_FOREACH takes care of
 differentiating between l-values and r-values and does the right thing to
 r-values):

 {{{
 #!cpp
 BOOST_FOREACH(const MapType::value_type &v, return_map_by_value())
   ...
 }}}

 It seems that boost::range::adapters need to do a similar thing to what
 BOOST_FOREACH is does to identify r-values and make a copy (which the
 compiler is likely to optimize away).


 Attached is a test sample and the resulting behavior.
 The output is from code compiled with g++ 4.6.3 with no optimizations.

 {{{
 $ g++ -I ../include/ container_test.cpp
 $ ./a.out
 Test #1 (local variable)
   Generating map
 key = '12345'
 key = 'QWERT'
 key = 'igor!'
 Test #2 (value_type)
   Generating map
 key = '12345'
 key = 'QWERT'
 key = 'igor!'
 Test #3 (temp ref)
   Generating map
 key = '12345'
 key = 'QWERT'
 key = 'igor!'
 Test #4 (range_iterator)
   Generating map
 key = '12345'
 key = 'QWERT'
 key = 'igor!'
 Test #5 (bug)
   Generating map
 key = '12345APãr`ãr¨ârãr1 ãrÿÿÿÿABCDE1ãrÿÿÿÿQWERTAâr½™ÿÀâr
 Ã¢rHãr¸ãr1àárÿÿÿÿqwertAärH½™ÿPärärHãr¸ãrAÃ¥rÐãârxârAÀãrÐãr¨ârãrAÀärX™ÿårÐärHãr¸ãrAäârxârAۊrär¨ârãrAیrؽ™ÿÐårårHãr¸ãrA°ârPåârxârA@Ã¥rPÃ¥r¨ârãr
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/9578>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:15 UTC