[CSHARP-4567] Support projections where the lambda body returns a type different from but assignable to the lambda return type Created: 13/Mar/23 Updated: 28/Oct/23 Resolved: 17/May/23 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | LINQ3, Serialization |
| Affects Version/s: | 2.19.0 |
| Fix Version/s: | 2.19.2 |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Tom Murphy | Assignee: | Robert Stam |
| Resolution: | Fixed | Votes: | 1 |
| Labels: | Bug, triage | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Attachments: |
|
| Backwards Compatibility: | Fully Compatible |
| Documentation Changes: | Not Needed |
| Documentation Changes Summary: | 1. What would you like to communicate to the user about this feature? |
| Description |
SummaryProjection LINQ expressions dynamically created throw InvalidCastException when the projection is applied to IFluentFind and executed in C# driver version 2.19.0. Exception Information: Unable to cast object of type 'MongoDB.Bson.Serialization.BsonClassMapSerializer`1[DynamicType0`2]' to type 'MongoDB.Bson.Serialization.IBsonSerializer`1[System.Object]'. at MongoDB.Driver.Linq.Linq3Implementation.LinqProviderAdapterV3.TranslateExpressionToProjection[TInput,TOutput](Expression`1 expression, IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions) How to ReproduceDownload the attached VS solution and run the project. The code contains comments with information regarding the issue. Additional BackgroundThe projection is created using a dynamically generated System.Type via IL (see attached solution). The type is similar to an anonymous type containing a subset of the actual properties defined on a specific type. The properties can be any combination of properties from the source type and are verified against the source type preventing invalid properties from being added to the projection. Once the projection Type is generated it is then used in the creation of a dynamic LINQ expression that represents the actual projection applied to the IFluentFind. As mentioned, the projection is similar to a projection created using an anonymous type. The anonymous type projection does not throw the exception though. The implementation described here has been in use for quite some time in our systems and has worked quite well in dozens of microservices deployed in the US and Europe. The issue was only realized recently when we updated to driver version v2.19.0. This implementation is part of a larger framework that is also used outside of MongoDB so this is a bit of a critical issue. The issue is related to the changes made to address MongoDB .NET/C# Driver vulnerable to Deserialization of Untrusted Data · CVE-2022-48282 · GitHub Advisory Database · GitHub I assume but it isn't clear if this change was intended to prevent the scenario described in our implementation. Based on the comments made by James_Kovacs here Vulnerability CVE-2022-48282 - Working with Data / Drivers & ODMs - MongoDB Developer Community Forums it seems like it should not. |
| Comments |
| Comment by Githook User [ 18/May/23 ] | |||
|
Author: {'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}Message: | |||
| Comment by Robert Stam [ 17/May/23 ] | |||
|
While the repro provided is rather complex (it generates expressions dynamically), the root cause was found to be a projection like this:
The lambda is declared to return `object` but the body returns a subclass of `object`. We were expecting the body to return a value whose type was the same as the return type of the lambda. We now support the body returning a value that is different from the lambda return type, as long as it is assignable to the lambda return type (which it must be, or the code would not have compiled in the first place). | |||
| Comment by Githook User [ 17/May/23 ] | |||
|
Author: {'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}Message: | |||
| Comment by Inclouds N/A [ 15/May/23 ] | |||
|
I can confirm that the problem appeared also for us, after upgrading to 2.19.1 version. | |||
| Comment by Robert Stam [ 12/May/23 ] | |||
|
Sorry for the delay in investigating this. It shouldn't matter whether the projection expression was generated by the compiler or by your own code. But it does make it a bit harder to figure out what is going on. Thanks for the solution you provided that reproduces the issue. It helped me figure out the root cause and how to reproduce it without using dynamic expression generation. I'm working on a fix now. | |||
| Comment by Tom Murphy [ 09/May/23 ] | |||
|
Is there any update? The fact that this issue is now unassigned is not encouraging. I have colleagues in Europe that have identified additional issues with projections when including them in aggregate pipelines in driver version 2.19.0 which is totally outside of my issue. I saw in your backlog that there are other people that have had projections broken because driver 2.19.0 is not backward compatible. Any information would be helpful for me to relay to my organization. |