New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C#: getting RecursionLimitExceeded with no way to configure #22682
Comments
The configuration doesn't really belong to the channel options, but we should think about how to make (de)serialization more configurable (we should go through this exercise when integrating the new protobuf C# parser from protocolbuffers/protobuf#7351). @JamesNK any thoughts? |
Configuration either needs to happen at runtime on channel - that would require a way to pass the configuration from the channel into the marshaller - or put it on Channel seems like a better place, but configuration shouldn't be tied to Google.Protobuf. It's a tricky problem. |
I just noticed this comment from @anandolee on another issue:
@mikhailshilkov I don't know yet what is this thing called |
Never mind my previous comment, I was looking at a completely different repo. 🤦 |
@sfmskywalker I guess this depends on whether this setting is exposed in the C# SDK. I have no idea yet... |
This issue/PR has been automatically marked as stale because it has not had any update (including commits, comments, labels, milestones, etc) for 30 days. It will be closed automatically if no further update occurs in 7 day. Thank you for your contributions! |
Digging into the details, I see CodedInputStream.ReadMessage calls ParsingPrimitivesMessages.ReadMessage where it throws InvalidProtocolBufferException. The message says:
I see this is available for Java at CodedInputStream.setRecursionLimit but not for C#. @jtattermusch @JamesNK could the equivalent be added to the C# class? 🙏 This is a showstopper as it is, so are there any workarounds in the meantime? |
@mikhailshilkov Pulumi should fork this repo and remove the recursion limit in the meantime, otherwise dotnet support is hosed. |
I created a separate issue in the protobuf repo protocolbuffers/protobuf#7995
There's no point in forking this repo. It's |
I filed grpc/grpc-dotnet#1983 to address the root cause of this problem. |
We've resorted to patching the internal state of // DOM aspects can be very deeply nested. Unfortunately, the recursion limit used when deserializing gRPC messages is
// not configurable through any publicly exposed API and the default is only 100. This very ugly hack intercepts calls
// to Dom.Document.Mergefrom(CodedInputStream) and uses reflection to alter the private member `recursionLimit` on
// the given `CodedInputStream` instance. The author feels dirty.
//
// IMPORTANT: This hack works with Grpc.Tools 2.32.0 and Google.Protobuf 3.13.0. If you upgrade any of these please
// make sure that this hack still works!
class UglyRecursionLimitMonkeyPatchHack
{
public static void Apply()
{
var harmony = new Harmony("com.siteimprove.pidan");
harmony.PatchAll();
}
[HarmonyPatch(typeof(Dom.Document), "MergeFrom", typeof(CodedInputStream))]
class Patch
{
public static void Prefix(ref CodedInputStream input)
{
var stateField = typeof(CodedInputStream).GetField(
"state", BindingFlags.NonPublic | BindingFlags.Instance);
var state = stateField.GetValue(input);
var recursionLimit = state.GetType().GetField("recursionLimit", BindingFlags.NonPublic | BindingFlags.Instance);
recursionLimit.SetValue(state, 1500);
stateField.SetValue(input, state);
}
}
} |
I'm going to close this issue since it's basically a duplicate of grpc/grpc-dotnet#1983 (once we have configurable marshallers, configuring the RecursionLimit for protobuf parsing will be easy). |
What version of gRPC and what language are you using?
C#, 2.24
What operating system (Linux, Windows,...) and version?
macOS Catalina 10.15.3
What runtime / compiler are you using (e.g. python version or version of gcc)
.NET Core 3.1
What did you do?
I'm sending a message with high level of recursion in it (a map containing a map containing a map etc.)
What did you expect to see?
C# client would successfully parse the gRPC response.
What did you see instead?
I get an exception:
The actual exception is swallowed but I got it with a debugger:
It happens on this line in Protobuf's
CodedInputStream
.Suggested solution
Please allow setting the max recursion level in the channel options.
The text was updated successfully, but these errors were encountered: