From 4781096a3cce8588c5dfc12cad8239e0ef8f1dac Mon Sep 17 00:00:00 2001 From: Jean-Jacques Lafay Date: Thu, 2 Feb 2023 16:27:38 +0100 Subject: [PATCH] Fix a couple of semi-edge-cases (#199) * Avoid throwing on IDisposable * 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. * 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. --------- Co-authored-by: Marc Gravell --- .../Configuration/ProtoBufMarshallerFactory.cs | 18 ++++++++++++++---- .../Internal/ContractOperation.cs | 4 +--- src/protobuf-net.Grpc/Internal/ProxyEmitter.cs | 9 +++++++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/protobuf-net.Grpc/Configuration/ProtoBufMarshallerFactory.cs b/src/protobuf-net.Grpc/Configuration/ProtoBufMarshallerFactory.cs index 4abdc7d..7595151 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; @@ -187,9 +187,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 diff --git a/src/protobuf-net.Grpc/Internal/ContractOperation.cs b/src/protobuf-net.Grpc/Internal/ContractOperation.cs index 11d9ce7..a943f37 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; @@ -212,8 +212,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; diff --git a/src/protobuf-net.Grpc/Internal/ProxyEmitter.cs b/src/protobuf-net.Grpc/Internal/ProxyEmitter.cs index 9e566d8..1d4b334 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.Client; using ProtoBuf.Grpc.Configuration; using System; @@ -212,7 +212,12 @@ FieldBuilder Marshaller(Type forType) var shallMethodBeImplemented = isService || isMethodInherited; if (!(shallMethodBeImplemented && 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; }