Boost C++ Libraries: Ticket #13481: Strict aliasing is causing SIGSEGV on ARM Cortex-A15 when using GCC6 https://svn.boost.org/trac10/ticket/13481 <p> Hello, I've been tracking a crach after upgrading GCC to 6.4 which was caused by corruption of the object stored inside <code>boost::function</code>. </p> <p> I think that the root cause for this is in the <code>function_buffer</code> storage. You see, there is a char member there with the intention of "relax aliasing constraints" as it states in the comment but if my understanding of the standard is correct, it doesn't really do that. Quote from the C++: </p> <pre class="wiki">If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined: 52 — the dynamic type of the object, — a cv-qualified version of the dynamic type of the object, — a type similar (as defined in 4.4) to the dynamic type of the object, — a type that is the signed or unsigned type corresponding to the dynamic type of the object, — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object, — an aggregate or union type that includes one of the aforementioned types among its elements or non- static data members (including, recursively, an element or non-static data member of a subaggregate or contained union), — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object, — a char or unsigned char type. </pre><p> There is indeed a <code>char</code> type along other things that may be aliased safely, but <code>function_buffer</code> is an <code>union</code> with <code>char</code> member so it falls into: </p> <pre class="wiki">an aggregate or union type that includes one of the **aforementioned** types </pre><p> so the <code>function_buffer</code> itself can't be aliased. There was similar bug on GCC: 77686 (I'm unable to put links here) which was fixed by applying <code>may_alias</code> attribute on their <code>function_buffer</code> counterpart. Seems reasonable but after applying it to <code>function_buffer</code> it was still failing but after reading GCC docs I think I've found out why: </p> <pre class="wiki">may_alias Accesses through **pointers to types** with this attribute are not subject to type- based alias analysis, but are instead assumed to be able to alias any other type of objects. In the context of section 6.5 paragraph 7 of the C99 standard, an lvalue expression dereferencing such a pointer is treated like having a character type. </pre><p> and there is <code>BOOST_FUNCTION_FUNCTION::move_assign</code> function which does: </p> <pre class="wiki">if (this-&gt;has_trivial_copy_and_destroy()) this-&gt;functor = f.functor; </pre><p> and as it doesn't operate on the pointers, <code>may_alias</code> seems to be simply ignored. So two things seems to fixing it (I hope they fix it, since the bug if quite "delicate" and it's easy to hide it by changing the code that doesn't seem relevant): </p> <p> 1) use <code>gnu::may_alias</code> on <code>function_buffer</code> and assign it trough some helper like this instead of <code>union</code>s assign operator: </p> <pre class="wiki">template&lt;class T&gt; void alias_safe_assign(T &amp; dst, T &amp; src) { dst = src; } </pre><p> there is Richard's comment on GCC bugtracker: 77686#c12 where he's noted about <code>std::swap</code> having a references so it seems to matter. </p> <p> 2) operate on <code>data</code> member directly since it has relaxed aliasing requirements by being a <code>char</code>. This doesn't even require GNU extensions.: </p> <pre class="wiki">std::memcpy(this-&gt;functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer)); </pre><p> Of course, putting a <code>may_alias</code> on the functor type itself (the one that I'm assigning to <code>boost::function</code> object) or putting this type into <code>function_buffer</code> also fixes this. </p> <hr /> <p> I'm compiling the attached testcase using </p> <pre class="wiki">arm-cortexa15-linux-gnueabihf-g++ (GCC) 6.4.1 20170811 </pre><p> and <code>-O2 -fPIC</code> </p> <p> Br, Piotr. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/13481 Trac 1.4.3 Piotr Podusowski <piotr.podusowski@…> Wed, 14 Mar 2018 08:44:14 GMT attachment set https://svn.boost.org/trac10/ticket/13481 https://svn.boost.org/trac10/ticket/13481 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">bug.cpp</span> </li> </ul> Ticket Joakim Tosteberg <joakim.tosteberg@…> Wed, 04 Apr 2018 06:55:03 GMT <link>https://svn.boost.org/trac10/ticket/13481#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13481#comment:1</guid> <description> <p> We have a similar issue using a gcc 6.3 compiler from <a class="ext-link" href="https://github.com/Broadcom/stbgcc-6.3/releases"><span class="icon">​</span>https://github.com/Broadcom/stbgcc-6.3/releases</a> </p> <p> In this case the issue does not reproduce with the attached bug.cpp but we have an another example, attached as crash.cpp which reproduces it with this compiler version when built with -O2 (and given that the issue seems quite sensitive to even small changes in the code I'm not surprised that slightly different compiler version requires different code to reproduce it). Adding -fno-strict-aliasing when building makes the issue go away. </p> <p> Also, using the suggested change to do a memcpy on the data member instead of directly assigning the functor inside function_template.hpp does seem to resolve the issue. </p> </description> <category>Ticket</category> </item> <item> <author>Joakim Tosteberg <joakim.tosteberg@…></author> <pubDate>Wed, 04 Apr 2018 06:55:34 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/13481 https://svn.boost.org/trac10/ticket/13481 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">crash.cpp</span> </li> </ul> Ticket Joakim Tosteberg <joakim.tosteberg@…> Wed, 04 Apr 2018 06:56:09 GMT attachment set https://svn.boost.org/trac10/ticket/13481 https://svn.boost.org/trac10/ticket/13481 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_strict_aliasing_fix.patch</span> </li> </ul> <p> Patch to fix the issue based on suggestion in original description </p> Ticket Piotr Podusowski <piotr.podusowski@…> Wed, 04 Apr 2018 07:19:43 GMT <link>https://svn.boost.org/trac10/ticket/13481#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13481#comment:2</guid> <description> <p> Hi, this fix was delivered to boost develop branch: <a class="ext-link" href="https://github.com/boostorg/function/pull/15"><span class="icon">​</span>https://github.com/boostorg/function/pull/15</a> </p> <p> Br, Piotr. </p> </description> <category>Ticket</category> </item> <item> <author>Joakim Tosteberg <joakim.tosteberg@…></author> <pubDate>Wed, 04 Apr 2018 07:24:05 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/13481#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13481#comment:3</guid> <description> <p> Ah, great! </p> <p> Down at row 907 in the same file in assign_to_own there is a very similar assignment this-&gt;functor = f.functor; don't that one have to be updated as well? </p> </description> <category>Ticket</category> </item> <item> <author>Piotr Podusowski <piotr.podusowski@…></author> <pubDate>Wed, 04 Apr 2018 07:26:56 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/13481#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13481#comment:4</guid> <description> <p> I didn't noticed it before, yes, I believe we should do that. Do you mind creating a pull request? </p> </description> <category>Ticket</category> </item> <item> <author>Joakim Tosteberg <joakim.tosteberg@…></author> <pubDate>Wed, 04 Apr 2018 07:41:16 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/13481#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/13481#comment:5</guid> <description> <p> Done: <a class="ext-link" href="https://github.com/boostorg/function/pull/16"><span class="icon">​</span>https://github.com/boostorg/function/pull/16</a> </p> </description> <category>Ticket</category> </item> </channel> </rss>