Ticket #4660: boost serialization binary archive compatibility fix.patch

File boost serialization binary archive compatibility fix.patch, 7.2 KB (added by markus.henschel@…, 10 years ago)

Fix for making binary archives created by ALL versions work

  • boost/archive/basic_binary_iarchive.hpp

     
    8282    // binary files don't include the optional information
    8383    void load_override(class_id_optional_type & /* t */, int){}
    8484
    85     void load_override(tracking_type & t, int /*version*/){
     85    void load_override(tracking_type & t, int version){
    8686        library_version_type lvt = this->get_library_version();
    87         if(boost::archive::library_version_type(6) < lvt){
    88             int_least8_t x=0;
    89             * this->This() >> x;
    90             t = boost::archive::tracking_type(x);
    91         }
    92         else{
    93             bool x=0;
    94             * this->This() >> x;
    95             t = boost::archive::tracking_type(x);
    96         }
    97     }
    98     void load_override(class_id_type & t, int version){
    99         library_version_type lvt = this->get_library_version();
    10087        if(boost::archive::library_version_type(7) < lvt){
    10188            this->detail_common_iarchive::load_override(t, version);
    10289        }
    103         else
    104         if(boost::archive::library_version_type(6) < lvt){
    105             int_least16_t x=0;
    106             * this->This() >> x;
    107             t = boost::archive::class_id_type(x);
    108         }
    10990        else{
    110             int x=0;
     91            char x=0;
    11192            * this->This() >> x;
    112             t = boost::archive::class_id_type(x);
     93            t = boost::archive::tracking_type(x);
    11394        }
    11495    }
    115     void load_override(class_id_reference_type & t, int version){
    116         load_override(static_cast<class_id_type &>(t), version);
    117     }
     96
    11897#if 0
    11998    void load_override(class_id_reference_type & t, int version){
    12099        library_version_type lvt = this->get_library_version();
     
    144123        if(boost::archive::library_version_type(7) < lvt){
    145124            this->detail_common_iarchive::load_override(t, version);
    146125        }
    147         else
    148         if(boost::archive::library_version_type(6) < lvt){
    149             uint_least8_t x=0;
    150             * this->This() >> x;
    151             t = boost::archive::version_type(x);
    152         }
    153         else
    154         if(boost::archive::library_version_type(5) < lvt){
    155             uint_least16_t x=0;
    156             * this->This() >> x;
    157             t = boost::archive::version_type(x);
    158         }
    159         else
    160         if(boost::archive::library_version_type(2) < lvt){
    161             // upto 255 versions
     126        else{
    162127            unsigned char x=0;
    163128            * this->This() >> x;
    164             t = version_type(x);
    165         }
    166         else{
    167             unsigned int x=0;
    168             * this->This() >> x;
    169129            t = boost::archive::version_type(x);
    170130        }
    171131    }
    172132
    173133    void load_override(boost::serialization::item_version_type & t, int version){
    174134        library_version_type lvt = this->get_library_version();
    175 //        if(boost::archive::library_version_type(7) < lvt){
    176         if(boost::archive::library_version_type(6) < lvt){
     135        if(boost::archive::library_version_type(7) < lvt){
    177136            this->detail_common_iarchive::load_override(t, version);
    178137        }
    179         else
    180         if(boost::archive::library_version_type(6) < lvt){
    181             uint_least16_t x=0;
    182             * this->This() >> x;
    183             t = boost::serialization::item_version_type(x);
    184         }
    185138        else{
    186             unsigned int x=0;
     139            unsigned char x=0;
    187140            * this->This() >> x;
    188141            t = boost::serialization::item_version_type(x);
    189142        }
    190143    }
    191144
    192145    void load_override(serialization::collection_size_type & t, int version){
    193         if(boost::archive::library_version_type(5) < this->get_library_version()){
     146        if(boost::archive::library_version_type(7) < this->get_library_version()){
    194147            this->detail_common_iarchive::load_override(t, version);
    195148        }
     149        else if(boost::archive::library_version_type(5) < this->get_library_version()){
     150            size_t x=0;
     151            * this->This() >> x;
     152            t = serialization::collection_size_type(x);
     153        }
    196154        else{
    197155            unsigned int x=0;
    198156            * this->This() >> x;
  • boost/archive/impl/basic_binary_iarchive.ipp

     
    7979    library_version_type input_library_version;
    8080    //* this->This() >> input_library_version;
    8181    {
     82                //Boost serialization 1.42, 1.43 and 1.44 all wrote archives with an archive version of 7.
     83                //1.42 and 1.43 used "version_type" as archive version type and explicitely stored it as "unsigned char" like other versions before.
     84                //1.44 started to use "library_version_type" to store the archive version as an "uint_least16_t" with two bytes but didn't increase the archive version.
     85        //1.45 finally increased the archive version. So the problem is to detect which version an archive with a version of 7 belongs to.
     86                //Fortunately the archive version is followed by a byte that contains sizeof(int) which cannot be zero and will currently not exceed 255.
     87                //This way the higher order byte of the 2 byte archive version will always be zero and can be used to detect which boost serialization version was used to write the archive.
     88                //If version 1.44 is detected the archive version is increased to 8. This kind of fixes the issue that 1.44 did not increase the archive version as it should have.
     89                //Fortunately 1.45 (the first version that writes archive version 8 binary archives) didn't do any changes in the way archives are writte by its own so this fix works.
     90
    8291        int v = 0;
    83         v = this->This()->m_sb.sbumpc();
     92        v = this->This()->m_sb.sbumpc();        //reads low order byte
    8493        #if defined(BOOST_LITTLE_ENDIAN)
    85         if(v < 6){
    86             ;
    87         }
    88         else
    8994        if(v < 7){
    90             // version 6 - next byte should be zero
    91             this->This()->m_sb.sbumpc();
     95            ;   //version 6 and below used "version_type" as archive version type and explicitely stored it as "unsigned char"
    9296        }
    9397        else
    9498        if(v < 8){
    9599            int x1;
    96             // version 7 = might be followed by zero or some other byte
    97             x1 = this->This()->m_sb.sgetc();
    98             // it's =a zero, push it back
    99             if(0 == x1)
     100            x1 = this->This()->m_sb.sgetc();    //reads possible high order byte
     101            // it's a zero, remove it from input stream
     102            if(0 == x1){
    100103                this->This()->m_sb.sbumpc();
     104                                ++v;    //increase archive version to 8
    101105        }
     106        }
    102107        else{
    103108            // version 8+ followed by a zero
    104109            this->This()->m_sb.sbumpc();
    105110        }
    106111        #elif defined(BOOST_BIG_ENDIAN)
    107         if(v == 0)
    108             v = this->This()->m_sb.sbumpc();
     112        if(v == 0){                                                             //check if high order byte is zero
     113            v = this->This()->m_sb.sbumpc();    //read the low order byte
     114                        if (7 == v)     
     115                                ++v;    //increase the archive version to 8 because it has a value of 7 and consists of 2 bytes
     116                }
    109117        #endif
    110118        input_library_version = static_cast<library_version_type>(v);
    111119    }