Opened 8 years ago
Closed 8 years ago
#11139 closed Bugs (fixed)
boost::container::vector<std::shared_ptr<const T>, std::allocator<T>>::const_iterator allows changing its dereferenced elements
Reported by: | Owned by: | Ion Gaztañaga | |
---|---|---|---|
Milestone: | To Be Determined | Component: | container |
Version: | Boost 1.57.0 | Severity: | Problem |
Keywords: | Cc: | felix.klar@… |
Description
Consider the following attempt to make a const_iterator
for a vector of smart pointers, be de-referentiable only to smart pointers to constant types:
#include <memory> #include <boost/container/vector.hpp> class C { public: using a_type = int; using shared_ptr = std::shared_ptr<a_type>; using shared_constptr = std::shared_ptr<const a_type>; // In my code, I am using a more complex allocator // in shared memory from boost::interprocess. using some_fixed_allocator = std::allocator<shared_ptr>; using vector = boost::container::vector<shared_ptr, some_fixed_allocator>; using cvector = boost::container::vector<shared_constptr, some_fixed_allocator>; C () { shared_ptr p = std::make_shared<a_type> (1); _v.push_back (p); } cvector::const_iterator first_element () const { return _v.begin (); } private: vector _v; }; int main () { C c; C::cvector::const_iterator it = c.first_element (); **it = 2; // Expecting an error! // Note that we have an error using std::vector. }
This compiled cleanly with G++ 4.9 with -std=c++11
, which really is hiding the problem as the const_iterator allows changing elements of a the cvector
type.
Using a std::vector at least results in the following compilation error:
allocator-rebind.cc: In member function ‘std::vector<boost::shared_ptr<const int>, std::allocator<int> >::const_iterator C::first_element() const’: allocator-rebind.cc:31:26: error: could not convert ‘((const C*)this)->C::_v.std::vector<_Tp, _Alloc>::begin<boost::shared_ptr<int>, std::allocator<int> >()’ from ‘std::vector<boost::shared_ptr<int>, std::allocator<int> >::const_iterator {aka __gnu_cxx::__normal_iterator<const boost::shared_ptr<int>*, std::vector<boost::shared_ptr<int>, std::allocator<int> > >}’ to ‘std::vector<boost::shared_ptr<const int>, std::allocator<int> >::const_iterator {aka __gnu_cxx::__normal_iterator<const boost::shared_ptr<const int>*, std::vector<boost::shared_ptr<const int>, std::allocator<int> > >}’ return _v.begin ();
I suspect all the other containers in boost::container suffer from the same problem, e.g. they allow compilation of something wrong.
Incidentally, it would be nice to have a way to rebind iterators for smart pointers, so that full encapsulation can be achieved also for const
accessor methods.
Change History (2)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Thanks for the report. Fixed in:
https://github.com/boostorg/container/commit/ad54608d780f489d3e3119a097046da4fc23ce4e
Hopefully in time for Boost 1.58
Says Ion Gaztañaga: