Boost C++ Libraries: Ticket #10432: 32-bit offset_ptr crashes on 64-bit platform https://svn.boost.org/trac10/ticket/10432 <p> There seem to be problems with handling offset_ptrs with 32-bit offsets on a 64-bit platform. The attached code sample tries to create a file mapping with managed_external_buffer using 32-bit offset_ptrs. The program crashes sometimes when trying to initialize the mapping (see the attached valgrind log for one of such crashes). The offset_ptr is declared as follows: </p> <pre class="wiki">typedef boost::interprocess::offset_ptr&lt; void, std::ptrdiff_t, std::int32_t &gt; void_pointer; </pre><p> My theory is that there are incorrect offset conversions somewhere in Boost.Interprocess which sometimes result in incorrect pointers and a subsequent crash. This may not happen on every run of the program because the mapping address of the file region can change between runs. </p> <p> One of the problems with 32-bit offset_ptrs is that its implementation performs implicit casts of the offset to std::size_t (see calls to offset_ptr_to_raw_pointer and offset_ptr_to_offset), which makes incorrect result if the offset type is unsigned and smaller than std::size_t. I didn't find any restrictions on the offset type in the docs or the code, and by default the offset type is unsigned. IMO, the code should be corrected to perform sign extension of the offset or restrict the offset type to be signed integers. This should be documented as well. </p> <p> However, even if my program uses a signed offset type, it still crashes, so there have to be other issues elsewhere. </p> <p> I tested this on Kubuntu 14.04 x86_64. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/10432 Trac 1.4.3 Andrey Semashev Sun, 31 Aug 2014 13:13:53 GMT attachment set https://svn.boost.org/trac10/ticket/10432 https://svn.boost.org/trac10/ticket/10432 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">offset_ptr_test.cpp</span> </li> </ul> <p> A test case to reproduce the crash </p> Ticket Andrey Semashev Sun, 31 Aug 2014 13:14:12 GMT attachment set https://svn.boost.org/trac10/ticket/10432 https://svn.boost.org/trac10/ticket/10432 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">valgrind.log</span> </li> </ul> <p> Valgrind output </p> Ticket Ion Gaztañaga Wed, 17 Sep 2014 20:02:48 GMT <link>https://svn.boost.org/trac10/ticket/10432#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10432#comment:1</guid> <description> <p> Using signed integers is problematic because overflow is undefined behaviour, there were problems with some compilers. And yes, offset_ptr was not thought to be used with integers smaller than size_t (or more strictly, smaller than uintptr_t). The option to customize the <a class="missing wiki">OffsetType</a> was to allow interoperability between 32 and 64 bit applications using 64 bit offset types. </p> <p> Many times, in a 64 bit OS, a 32 bit offset type can't hold the distance between a stack variable and a shared memory address, as the OS can place them further than 4GB. </p> <p> This is not documented and it should be explained. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrey Semashev</dc:creator> <pubDate>Thu, 18 Sep 2014 03:12:12 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/10432#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/10432#comment:2</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/10432#comment:1" title="Comment 1">igaztanaga</a>: </p> <blockquote class="citation"> <p> Using signed integers is problematic because overflow is undefined behaviour, there were problems with some compilers. </p> </blockquote> <p> Then I think the sign extension should be coded explicitly. Since offset_ptr is supposed to point to locations before itself, the offset is logically a signed value (i.e. analogous to ptrdiff_t rather than size_t). </p> <blockquote class="citation"> <p> And yes, offset_ptr was not thought to be used with integers smaller than size_t (or more strictly, smaller than uintptr_t). The option to customize the <a class="missing wiki">OffsetType</a> was to allow interoperability between 32 and 64 bit applications using 64 bit offset types. </p> <p> Many times, in a 64 bit OS, a 32 bit offset type can't hold the distance between a stack variable and a shared memory address, as the OS can place them further than 4GB. </p> <p> This is not documented and it should be explained. </p> </blockquote> <p> If it's absolutely not possible to use offset_ptr with offsets smaller than ptrdiff_t then there should be a static assert prohibiting that. </p> <p> But I wonder if it's necessary to store offset_ptrs on the stack. Is it possible to operate with offset_ptr in-place and only store normal pointers on the stack? </p> </description> <category>Ticket</category> </item> </channel> </rss>