id summary reporter owner description type status milestone component version severity resolution keywords cc 6856 Critical problem with serialization and class versioning harris.pc@… Robert Ramey "I am investigating strange error ""input stream error"" messages that I've been getting for a while when loading XML archives, and it turns out that boost::serialization is no longer enforcing strictly incrementing versioning numbers. Specifically the patch: https://github.com/ryppl/boost-svn/commit/66e85ade721a82bbc2e082749d6af2eefcb63dcb#boost/archive/detail Which has the comment: {{{ + // note: we now comment this out. Before we permited archive + // version # to be very large. Now we don't. To permit + // readers of these old archives, we have to suppress this + // code. Perhaps in the future we might re-enable it but + // permit its suppression with a runtime switch. }}} I checked the documentation, and it is still assuming that class versions always increment, and it is implied (to me) that if a class version in an archive is larger than the BOOST_CLASS_VERSION() in the source, then it will not load (and checking the code, looks like it should throw a unsupported_class_version error). This is a critical problem, and is now my likely candidate for the reason why sometimes my programs crash when loading binary archives that are written by a newer version of my program. Basically, it NEVER checks if we are loading an archive that is newer than what the program is supported.  Thus, it will assume that it is reading the correct-versioned archive and serialize the wrong data in the wrong order. I wrote a small program to demonstrate the problem, most of the code was copied from the ""bus"" example in the documentation. The Makefile compiles 4 different versions:  xml and binary variants, each that write either version=0, version=1 classes. It is a program that loads an archive file (if the file can be opened), and then writes an archive file. The class written is a simple class with two integer variables. In version=0, it writes var1. In version=1, it writes var2, and then var1. This is what it looks like when you run the programs: {{{ $ ./test_version_binary_0 Could not open file to read: bus_route.binary Saved, var1=1 ------- so a binary archive is written to disk, version=0 $ ./test_version_binary_1 Restored, var1=1 var2=2 Saved, var1=1 var2=2 ------- archive was loaded correctly, and then written back to disk, now version=1 ------- now lets try and run the version=0 program $ ./test_version_binary_0 Restored, var1=2 FAIL! var1 should always be 1 $  ------- archive was loaded, apparently without error, but inspecting the data reveals that var1 was loaded with var2's value. }}} For the XML archive, we fortunately catch the problem, but only because it was expecting a different set of xml-tags: {{{ $ ./test_version_xml_0  Could not open file to read: bus_route.xml Saved, var1=1 $ ./test_version_xml_1 Restored, var1=1 var2=2 Saved, var1=1 var2=2 $ ./test_version_xml_0 terminate called after throwing an instance of 'boost::archive::xml_archive_exception'   what():  XML start/end tag mismatch - var1 Aborted $  }}} It seems to me that there are three solutions to this situation: 1) ignore problem.  allow boost-based software to incorrectly load binary archives. 2) change the documentation, tell users that they will need to manually test the version passed to void serialize(Archive,int) methods, and throw exceptions themselves if required. That will also mean upgrading all of the existing software and adding a test into every single serialize() function/method in existing production code. 3) turn back on the version check that was turned off in the above patch. This is what it looks like when I change the #if 0 to #if 1 {{{ $ ./test_version_binary_0 terminate called after throwing an instance of 'boost::archive::archive_exception'   what():  class version 9bus_route Aborted }}} And that's what I was expecting it to do. " Bugs new To Be Determined serialization Boost 1.49.0 Problem