Uploaded image for project: 'Ignite'
  1. Ignite
  2. IGNITE-13563

Deserializing IBinaryObject containing an IBinaryObject field fails

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 2.8.1
    • 2.10, 2.9.1
    • binary, platforms
    • Arch Linux (updated Oct 5): Linux 5.8.12, DotNet 3.1.108, OpenJDK 1.8.0_265.

    • Patch

    Description

      When one has a data object which has an IBinaryObject property, like so:

      class Model {
          public IBinaryObject Value { get; set; }
      }
      

      .. and proceeds to fill that property with an IBinaryObject of an unknown type (e.g. a binary object from a cache that has WithKeepBinary on):

      var binary = ignite.GetBinary();
      var model = new Model { Value = binary.GetBuilder("nonexistent").Build() };
      

      Then, the resulting object is savable/loadable from caches, as expected:

      var cache = ignite.GetOrCreateCache<string, Model>("models");
      cache.Put("model", model);
      var modelFromCache = cache.Get("model"); // Equivalent to model
      

      However, trying to convert the object to IBinaryObject (using ToBinary) and then deserializing that manually fails:

      var binaryObject = binary.ToBinary<IBinaryObject>(model);
      var modelFromBinary = binaryObject.Deserialize<Model>(); // Unknown pair [platformId=1, typeId=486454369]
      

      I have attached a program which reproduces the issue.


      After investigating the issue, it seems to occur because BinaryObject.Deserialize<T>() uses BinaryMode.Deserialize. This, in turn, causes BinaryReader.ReadBinaryObject() to call BinaryReader.Deserialize() for the first BinaryTypeId.Binary object found (while switching to BinaryMode.KeepBinary for nested objects). Then, BinaryReader.ReadFullObject() gets called, and not knowing better, tries to deserialize the object of a nonexistent type.

      Now, BinaryMode.Deserialize is also used by CacheClient. However, upon further investigation of the values passed to Marshaller.Unmarshall, CacheClient unmarshalls values starting with BinaryTypeId.Binary, while BinaryObject unmarshalls values starting directly with BinaryUtils.HdrFull; thus, BinaryReader functions correctly for caches but fails with binary objects.

      Due to the this, I think the proper fix would be to change BinaryObject.Deserialize<T>() to use BinaryMode.KeepBinary. I have attached a patch file containing that fix and an accompanying test.

      Attachments

        1. 0001-Fix-IBinaryObject-Deserialize.patch
          3 kB
          Bojidar Marinov
        2. Program.cs
          1 kB
          Bojidar Marinov

        Issue Links

          Activity

            People

              bojidar-bg Bojidar Marinov
              bojidar-bg Bojidar Marinov
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 20m
                  20m