Bojidar Marinov created IGNITE-13563:
----------------------------------------

             Summary: Deserializing IBinaryObject containing an IBinaryObject 
field fails
                 Key: IGNITE-13563
                 URL: https://issues.apache.org/jira/browse/IGNITE-13563
             Project: Ignite
          Issue Type: Bug
          Components: binary, platforms
    Affects Versions: 2.8.1
         Environment: Arch Linux (updated Oct 5): Linux 5.8.12, DotNet 3.1.108, 
OpenJDK 1.8.0_265.
            Reporter: Bojidar Marinov
         Attachments: 0001-Fix-IBinaryObject-Deserialize.patch, Program.cs

When one has a data object which has an IBinaryObject property, like so:
{code:c#}
class Model {
    public IBinaryObject Value { get; set; }
}
{code}
.. 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):
{code:c#}
var binary = ignite.GetBinary();
var model = new Model { Value = binary.GetBuilder("nonexistent").Build() };
{code}
Then, the resulting object is savable/loadable from caches, as expected:
{code:c#}
var cache = ignite.GetOrCreateCache<string, Model>("models");
cache.Put("model", model);
var modelFromCache = cache.Get("model"); // Equivalent to model
{code}
However, trying to convert the object to IBinaryObject (using ToBinary) and 
then deserializing that manually fails:
{code:c#}
var binaryObject = binary.ToBinary<IBinaryObject>(model);
var modelFromBinary = binaryObject.Deserialize<Model>(); // Unknown pair 
[platformId=1, typeId=486454369]
{code}
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.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to