From 058b70e2522b21443e010e211018331c3fea43ea Mon Sep 17 00:00:00 2001 From: Jean-Jacques Lafay Date: Wed, 13 Oct 2021 10:44:12 +0200 Subject: [PATCH 1/3] Avoid throwing on IDisposable --- src/protobuf-net.Grpc/Internal/ProxyEmitter.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/protobuf-net.Grpc/Internal/ProxyEmitter.cs b/src/protobuf-net.Grpc/Internal/ProxyEmitter.cs index ba21c12e..411fcbeb 100644 --- a/src/protobuf-net.Grpc/Internal/ProxyEmitter.cs +++ b/src/protobuf-net.Grpc/Internal/ProxyEmitter.cs @@ -1,4 +1,4 @@ -using Grpc.Core; +using Grpc.Core; using ProtoBuf.Grpc.Configuration; using System; using System.Collections.Generic; @@ -204,7 +204,12 @@ FieldBuilder Marshaller(Type forType) var il = impl.GetILGenerator(); if (!(isService && ContractOperation.TryIdentifySignature(iMethod, binderConfig, out var op, null))) { - il.ThrowException(typeof(NotSupportedException)); + // it is frequent for some infrastructure code to always call Dispose() on IDisposable, + // for instance Asp.Net Core dependency injection, so we don't want to throw in this case + if (iType == typeof(IDisposable) && iMethod.Name == nameof(IDisposable.Dispose)) + il.Emit(OpCodes.Ret); + else + il.ThrowException(typeof(NotSupportedException)); continue; } From 21c18675d5753992973022084d7acfecffe5c48d Mon Sep 17 00:00:00 2001 From: Jean-Jacques Lafay Date: Wed, 29 Sep 2021 11:04:25 +0200 Subject: [PATCH 2/3] Avoid throwing in ProtoBufMarshallerFactory.CanSerialize There is at least one situation where the underlying protobuf TypeModel throws a NotSupportedException : when asking about an array of arrays. While this seems doubtful (it should simply return false), it is easy enough to prevent this from trashing the whole service. --- .../Configuration/ProtoBufMarshallerFactory.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/protobuf-net.Grpc/Configuration/ProtoBufMarshallerFactory.cs b/src/protobuf-net.Grpc/Configuration/ProtoBufMarshallerFactory.cs index ef1e4b2d..36447dc8 100644 --- a/src/protobuf-net.Grpc/Configuration/ProtoBufMarshallerFactory.cs +++ b/src/protobuf-net.Grpc/Configuration/ProtoBufMarshallerFactory.cs @@ -1,4 +1,4 @@ -using ProtoBuf.Meta; +using ProtoBuf.Meta; using System; using System.Buffers; using System.IO; @@ -182,9 +182,19 @@ private T ContextualDeserialize(global::Grpc.Core.DeserializationContext cont /// Indicates whether a type should be considered as a serializable data type /// protected internal override bool CanSerialize(Type type) - => HasSingle(Options.ContractTypesOnly) - ? _model.CanSerializeContractType(type) - : _model.CanSerialize(type); + { + try + { + return HasSingle(Options.ContractTypesOnly) + ? _model.CanSerializeContractType(type) + : _model.CanSerialize(type); + } + catch (NotSupportedException) + { + // a typical case is the use of jagged arrays + return false; + } + } /// /// Deserializes an object from a payload From f2784fd894d484239e3a974a4a89048c89cfdd3a Mon Sep 17 00:00:00 2001 From: Jean-Jacques Lafay Date: Thu, 14 Oct 2021 15:10:56 +0200 Subject: [PATCH 3/3] Remove remnant of old code No longer any reason to handle delegates specifically : it will be done naturally by the marshallerCache (and who knows, maybe it *can* serialize some delegates !). Moreover, this could misinterpret a signature as valid without parameter, with somewhat weird consequences. --- src/protobuf-net.Grpc/Internal/ContractOperation.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/protobuf-net.Grpc/Internal/ContractOperation.cs b/src/protobuf-net.Grpc/Internal/ContractOperation.cs index d2a337eb..b79f70d4 100644 --- a/src/protobuf-net.Grpc/Internal/ContractOperation.cs +++ b/src/protobuf-net.Grpc/Internal/ContractOperation.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Reflection; using Grpc.Core; @@ -179,8 +179,6 @@ static TypeCategory GetCategory(MarshallerCache marshallerCache, Type type, IBin if (genType == typeof(AsyncServerStreamingCall<>)) return TypeCategory.AsyncServerStreamingCall; } - if (typeof(Delegate).IsAssignableFrom(type)) return TypeCategory.None; // yeah, that's not going to happen - if (marshallerCache.CanSerializeType(type)) return TypeCategory.Data; bindContext?.LogWarning("Type cannot be serialized; ignoring: {0}", type.FullName); return TypeCategory.Invalid; @@ -205,7 +203,7 @@ internal static bool TryIdentifySignature(MethodInfo method, BinderConfiguration if (method.IsGenericMethodDefinition) return false; // can't work with methods if ((method.Attributes & (MethodAttributes.SpecialName)) != 0) return false; // some kind of accessor etc - + if (!binderConfig.Binder.IsOperationContract(method, out var opName)) return false; var args = method.GetParameters();