Boost C++ Libraries: Ticket #13635: circular_buffer does not always initialize elements https://svn.boost.org/trac10/ticket/13635 <p> The circular_buffer erroneously mark some sections of the buffer as initialized, which can lead to use of uninitialized memory for non-trivial classes in the <code>insert</code> function. The problem appears to come from the <code>is_uninitialized</code> function, which does not properly handle the buffer state when <code>m_buff &lt; m_first &lt; m_last</code>. </p> <div class="wiki-code"><div class="code"><pre><span class="kt">bool</span> <span class="nf">is_uninitialized</span><span class="p">(</span><span class="n">const_pointer</span> <span class="n">p</span><span class="p">)</span> <span class="k">const</span> <span class="n">BOOST_NOEXCEPT</span> <span class="p">{</span> <span class="k">return</span> <span class="n">p</span> <span class="o">&gt;=</span> <span class="n">m_last</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">m_first</span> <span class="o">&lt;</span> <span class="n">m_last</span> <span class="o">||</span> <span class="n">p</span> <span class="o">&lt;</span> <span class="n">m_first</span><span class="p">);</span> <span class="p">}</span> </pre></div></div><p> In this case, e.g. <code>p = m_buff</code> will be flagged as initialized since <code>p &gt;= m_last</code> is <code>false</code>. </p> <p> A proper check would be: </p> <div class="wiki-code"><div class="code"><pre><span class="kt">bool</span> <span class="nf">is_uninitialized</span><span class="p">(</span><span class="n">const_pointer</span> <span class="n">p</span><span class="p">)</span> <span class="k">const</span> <span class="n">BOOST_NOEXCEPT</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">m_first</span> <span class="o">&lt;</span> <span class="n">m_last</span><span class="p">)</span> <span class="k">return</span> <span class="n">p</span> <span class="o">&gt;=</span> <span class="n">m_last</span> <span class="o">||</span> <span class="n">p</span> <span class="o">&lt;</span> <span class="n">m_first</span><span class="p">;</span> <span class="k">return</span> <span class="n">p</span> <span class="o">&gt;=</span> <span class="n">m_last</span> <span class="o">&amp;&amp;</span> <span class="n">p</span> <span class="o">&lt;</span> <span class="n">m_first</span><span class="p">;</span> <span class="p">}</span> </pre></div></div><p> Minimal reproducing program: </p> <div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/circular_buffer.hpp&gt;</span><span class="cp"></span> <span class="cm">/*</span> <span class="cm">$ g++ --version | head -n1</span> <span class="cm">g++ (GCC) 8.1.1 20180531</span> <span class="cm">$ g++ example.cpp -o example &amp;&amp; valgrind --tool=memcheck ./example 2&gt;&amp;1 | grep Invalid</span> <span class="cm">==19349== Invalid write of size 8</span> <span class="cm">==19349== Invalid write of size 2</span> <span class="cm">==19349== Invalid free() / delete / delete[] / realloc()</span> <span class="cm">*/</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">x</span><span class="p">(</span><span class="mi">7</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="mi">8</span><span class="p">);</span> <span class="c1">// has non-trivial move/copy</span> <span class="n">boost</span><span class="o">::</span><span class="n">circular_buffer</span><span class="o">&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">buffer</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> <span class="n">buffer</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">x</span><span class="p">);</span> <span class="c1">// [x| | ]</span> <span class="n">buffer</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">x</span><span class="p">);</span> <span class="c1">// [x|x| ]</span> <span class="n">buffer</span><span class="p">.</span><span class="n">pop_front</span><span class="p">();</span> <span class="c1">// [ |x| ]</span> <span class="n">buffer</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">buffer</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="mi">2</span><span class="p">,</span> <span class="n">y</span><span class="p">);</span> <span class="c1">// is_uninitialized(i) -&gt; [0,0,1] (should be [1,0,1])</span> <span class="c1">// [copy 1 -&gt; 0] : [x|x| ] bad copy to uninitialized element</span> <span class="c1">// [copy y -&gt; 1] : [x|y| ] ok</span> <span class="c1">// [construct y -&gt; 2] : [x|y|y] ok</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// tries to destruct uninitialized entry</span> <span class="p">}</span> </pre></div></div> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/13635 Trac 1.4.3 Niklas Fejes <niklas.fejes@…> Tue, 17 Jul 2018 08:45:14 GMT <link>https://svn.boost.org/trac10/ticket/13635#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13635#comment:1</guid> <description> <p> Submitted pull request at: <a class="ext-link" href="https://github.com/boostorg/circular_buffer/pull/17"><span class="icon">​</span>https://github.com/boostorg/circular_buffer/pull/17</a> </p> </description> <category>Ticket</category> </item> </channel> </rss>