Boost C++ Libraries: Ticket #3990: [serialization] data loss in version field https://svn.boost.org/trac10/ticket/3990 <p> Encfs uses a version which is a date in the from "YYYYMMDD". </p> <p> This is common: date stamps have been used for decades in manually-entered records (such as DNS records), as well as automatically in distributed system - such as with Lamport clocks that incorporate real-time components. </p> <p> There is data loss: version 1.42 silently corrupts the version field of programs using more then 16 bits for a version number. We can argue about how important the data is, but regardless, this change CAUSES DATA LOSS. Data loss is the worst thing a serialization or archival system can do - there would have been less impact of adding a random core dump 50% of the time then in loosing even 1 bit of data 100% of the time for affected applications. </p> <p> End users are starting to be affected: deployment systems which build from source, such as Macports, are starting to build against boost 1.42. This causes compatibility problems and end users are getting the short end of the stick in the form of archives that can't be read. </p> <p> The quicker this is fixed, the better, before longer-cycle deployments pick this up. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3990 Trac 1.4.3 darose@… Tue, 09 Mar 2010 18:10:08 GMT cc set https://svn.boost.org/trac10/ticket/3990#comment:1 https://svn.boost.org/trac10/ticket/3990#comment:1 <ul> <li><strong>cc</strong> <span class="trac-author">darose@…</span> added </li> </ul> Ticket Robert Ramey Tue, 09 Mar 2010 18:43:20 GMT status changed https://svn.boost.org/trac10/ticket/3990#comment:2 https://svn.boost.org/trac10/ticket/3990#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> <p> I'm still looking at this. </p> <p> I may be able to make changes to accomodate older archives which used a version # exceeding the originally expected 8 bits. I expect to enforce the 8 bit expectation in the future to avoid these problems. So you would be left with the capability of reading old archives, but the version number stored would have to be limited to 8 bits. So class using the "old version numbers" would have to be enhanced to make the switch as they are loaded. I don't know if this would be acceptable to you. </p> <p> Robert Ramey </p> Ticket ck@… Tue, 16 Mar 2010 23:50:49 GMT cc changed https://svn.boost.org/trac10/ticket/3990#comment:3 https://svn.boost.org/trac10/ticket/3990#comment:3 <ul> <li><strong>cc</strong> <span class="trac-author">ck@…</span> added </li> </ul> Ticket smr@… Wed, 26 May 2010 00:03:06 GMT <link>https://svn.boost.org/trac10/ticket/3990#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3990#comment:4</guid> <description> <p> Robert: any news? I guess the fix didn't make it into 1.43? Is there a way for encfs to cope? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Sun, 30 May 2010 16:06:10 GMT</pubDate> <title>status, type changed; resolution set https://svn.boost.org/trac10/ticket/3990#comment:5 https://svn.boost.org/trac10/ticket/3990#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>type</strong> <span class="trac-field-old">Bugs</span> → <span class="trac-field-new">Feature Requests</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> I can't fix this. I'm not going to expand the version # definition beyond the originally contemplated 8 bits. I can prevent it from happening in the future and this is what's been done. That is, violations of the 8 bit limitation will be trapped as soon as possible. </p> <p> So if you want maintain you're system of using dates for version numbers, you'll have to implement it yourself. This is fairly easy if you want to do it. e.g. </p> <pre class="wiki">template&lt;class Archive&gt; void serialization(Archive &amp; ar, unsigned int version){ // don't use the boost serialization number, use ours instead ar &amp; my_date; ar &amp;&amp; old_data_items if(ar.is_loading) if(my_date &gt; "jan 10, 2010") ar &amp; new_data_item; </pre><p> Of course this begs the question about how to use the old archives. This can be addressed with the function get_library_version() which returns an integer indicating which version of he api is being called. The library version number associated to boost 1.42 (I believe the last one which would work for you) is 5. So the above would be enhanced to be </p> <pre class="wiki">template&lt;class Archive&gt; void serialization(Archive &amp; ar, unsigned int version){ library_version_type library_version = get_library_version if(library_version &lt; 6) // the library version is a date my_date = version; else{ // don't use the boost serialization number, use ours instead ar &amp; my_date; } ar &amp;&amp; old_data_items if(ar.is_loading) if(my_date &gt; "jan 10, 2010") ar &amp; new_data_item; </pre><p> Alternatively if you want to give up on using the date as a version number you can make the transition like this: </p> <pre class="wiki">template&lt;class Archive&gt; void serialization(Archive &amp; ar, unsigned int version){ library_version_type library_version = get_library_version if(library_version &lt; 6) // the library version is a date // look up integer version # from a table version = convert_date_to_version_number(version) } ar &amp; old_data_items if(ar.is_loading){ if(version &gt; 9?) ar &amp; new_data_items; } </pre><p> I realize that this is likely not the answer you were interested in, but it DOES address the issue of handling old archives and it will transition you to a method of handling versioning consistent with the design of the boost serialization library. </p> <p> Robert Ramey </p> Ticket smr@… Sun, 30 May 2010 18:13:00 GMT <link>https://svn.boost.org/trac10/ticket/3990#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3990#comment:6</guid> <description> <p> Thanks for the hints, Robert. I'll pass on your suggestions to the Debian users and encfs maintainers. </p> <p> By the way: this broke for encfs in Boost version 1.42, so your example needs a slight modification. It is known to work for Boost 1.40; not sure about 1.41. </p> </description> <category>Ticket</category> </item> <item> <author>vgough@…</author> <pubDate>Wed, 16 Jun 2010 05:39:35 GMT</pubDate> <title>status, version, severity, milestone changed; resolution deleted https://svn.boost.org/trac10/ticket/3990#comment:7 https://svn.boost.org/trac10/ticket/3990#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>version</strong> <span class="trac-field-old">Boost 1.42.0</span> → <span class="trac-field-new">Boost 1.43.0</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">wontfix</span> </li> <li><strong>severity</strong> <span class="trac-field-old">Showstopper</span> → <span class="trac-field-new">Problem</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.43.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> <p> The internal archive version checking gets in the way of providing backward compatibility. </p> <p> BOOST_CLASS_VERSION(..., 20080816) fails at compile time as of boost 1.43. However the internal comparison is not done with 8bit values! </p> <p> I could call BOOST_CLASS_VERSION(..., 255) as the largest 8bit value, but internally when boost 1.43 reads an archive with version 20080816, it truncates that to 26797, decides that is larger then 255 and throws an archive exception. </p> <p> My work around has been to implement a partial specialization of iserializer for my class which eliminates the version number check in load_object_data, so that I can apply my own version checking in my load function. </p> <p> Having to specialize functions in boost::archive::detail seems undesirable. Is there a supported way to stop boost from doing the archive version comparison itself? </p> Ticket Robert Ramey Wed, 16 Jun 2010 06:02:54 GMT <link>https://svn.boost.org/trac10/ticket/3990#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3990#comment:8</guid> <description> <p> Hmmm - did you look at using library_version as shown above? I don't see why this woudn't give you what you want. That is if library_version &lt; 5? then use you're old system, otherwise, use your new system. I don't think you'd need to specialize anything in the archive. I believe it could be done in the serialization functions for each class. </p> <p> Robert Ramey </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Wed, 07 Jul 2010 16:42:24 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/3990#comment:10 https://svn.boost.org/trac10/ticket/3990#comment:10 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">wontfix</span> </li> </ul> <p> Guess I have to close this now. </p> Ticket