IGNITE-2026: .NET: Fixed stack overflow caused by incorrect unboxing of value types.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/efe632b1 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/efe632b1 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/efe632b1 Branch: refs/heads/ignite-843-rc2 Commit: efe632b18e760f699bedee906050f66eabadb077 Parents: 8ca163b Author: Pavel Tupitsyn <ptupit...@gridgain.com> Authored: Tue Dec 8 15:59:23 2015 +0300 Committer: vozerov-gridgain <voze...@gridgain.com> Committed: Tue Dec 8 15:59:23 2015 +0300 ---------------------------------------------------------------------- .../Binary/BinarySelfTest.cs | 67 ++++++++++++++++++++ .../Impl/Binary/BinaryReflectiveActions.cs | 4 +- .../Impl/Common/DelegateConverter.cs | 15 +++-- 3 files changed, 78 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/efe632b1/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs index 88328ec..9232665 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs @@ -1028,6 +1028,20 @@ namespace Apache.Ignite.Core.Tests.Binary CheckObject(marsh, new OuterObjectType(), new InnerObjectType()); } + [Test] + public void TestStructsReflective() + { + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new[] {new BinaryTypeConfiguration(typeof (ReflectiveStruct))} + }); + + var obj = new ReflectiveStruct(15, 28.8); + var res = marsh.Unmarshal<ReflectiveStruct>(marsh.Marshal(obj)); + + Assert.AreEqual(res, obj); + } + /** * <summary>Test handles.</summary> */ @@ -2228,5 +2242,58 @@ namespace Apache.Ignite.Core.Tests.Binary return Foo; } } + + private struct ReflectiveStruct : IEquatable<ReflectiveStruct> + { + private readonly int _x; + private readonly double _y; + + public ReflectiveStruct(int x, double y) + { + _x = x; + _y = y; + } + + public int X + { + get { return _x; } + } + + public double Y + { + get { return _y; } + } + + public bool Equals(ReflectiveStruct other) + { + return _x == other._x && _y.Equals(other._y); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + return false; + + return obj is ReflectiveStruct && Equals((ReflectiveStruct) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (_x*397) ^ _y.GetHashCode(); + } + } + + public static bool operator ==(ReflectiveStruct left, ReflectiveStruct right) + { + return left.Equals(right); + } + + public static bool operator !=(ReflectiveStruct left, ReflectiveStruct right) + { + return !left.Equals(right); + } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/efe632b1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs index b229898..15509fc 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs @@ -398,9 +398,7 @@ namespace Apache.Ignite.Core.Impl.Binary // Assign field value var targetParam = Expression.Parameter(typeof(object)); - var targetParamConverted = Expression.Convert(targetParam, field.DeclaringType); - var assignExpr = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParamConverted, - readExpr); + var assignExpr = Expression.Call(DelegateConverter.GetWriteFieldMethod(field), targetParam, readExpr); // Compile and return return Expression.Lambda<BinaryReflectiveReadAction>(assignExpr, targetParam, readerParam).Compile(); http://git-wip-us.apache.org/repos/asf/ignite/blob/efe632b1/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs index d32d475..5d1a4e2 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/DelegateConverter.cs @@ -250,20 +250,25 @@ namespace Apache.Ignite.Core.Impl.Common { Debug.Assert(field != null); - var module = Assembly.GetExecutingAssembly().GetModules()[0]; + var declaringType = field.DeclaringType; - var method = new DynamicMethod(string.Empty, null, new[] { field.DeclaringType, field.FieldType }, module, - true); + Debug.Assert(declaringType != null); // static fields are not supported - var il = method.GetILGenerator(); + var method = new DynamicMethod(string.Empty, null, new[] { typeof(object), field.FieldType }, + declaringType, true); + var il = method.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + + if (declaringType.IsValueType) + il.Emit(OpCodes.Unbox, declaringType); // modify boxed copy + il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, field); il.Emit(OpCodes.Ret); return method; } - } } \ No newline at end of file