EnumRepresentationConvention.CouldApply causes StackOverflowException on self-referencing IEnumerable<T> types (e.g. JToken)

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Critical - P2
    • 3.9.0
    • Affects Version/s: 3.8.0, 3.7.1, 3.8.1
    • Component/s: None
    • None
    • None
    • Fully Compatible
    • Dotnet Drivers
    • Not Needed
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      After upgrading from MongoDB.Driver 3.7.0 to 3.7.1+, applications that register an EnumRepresentationConvention and serialize types containing JToken (or any self-referencing IEnumerable<T>) crash with a StackOverflowException during convention application.

      Affects Version/s: 3.7.1, 3.8.0

      Component: BSON

      How to Reproduce

      1. Register a convention pack containing EnumRepresentationConvention:

      var conventionPack = new ConventionPack
      {
          new EnumRepresentationConvention(BsonType.String)
      };
      ConventionRegistry.Register("conventions", conventionPack, _ => true);
      
      

      2. Have a document class with a JObject or JToken property:

      public class MyDocument
      {
          public string Id { get; set; }
          public JObject Manifest { get; set; }
      }
      

      3. Perform any MongoDB operation that triggers class map auto-mapping for MyDocument.
      4. The process crashes with exit code 134 (SIGABRT) due to a StackOverflowException.

      Root Cause

      EnumRepresentationConvention.CouldApply (introduced by the fix for CSHARP-5905) recursively walks the generic arguments of IEnumerable<T> to check whether any nested type is an enum. JToken implements IEnumerable<JToken>, creating a cycle: JToken → IEnumerable<JToken> → JToken → … — infinite recursion with no visited-type guard.

      Stack trace (repeating segment):

      at MongoDB.Bson.Serialization.Conventions.EnumRepresentationConvention.CouldApply(System.Type)
      at MongoDB.Bson.Serialization.Conventions.EnumRepresentationConvention.CouldApply(System.Type)
      at MongoDB.Bson.Serialization.Conventions.EnumRepresentationConvention.CouldApply(System.Type)
      ...
      

      Expected Behavior

      CouldApply should track visited types (e.g. via a HashSet<Type>) to detect cycles and return false when encountering a previously seen type.

      Workaround

      Pin MongoDB.Driver to 3.7.0 and remove EnumRepresentationConvention from the convention pack, registering explicit EnumSerializer<T>(BsonType.String) for each enum type instead.

      Related Issues

      • CSHARP-5493 — Same StackOverflow bug in 3.2.0, fixed in 3.2.1 (the fix was reverted/regressed)
      • CSHARP-5905 — The fix that introduced CouldApply, which caused this regression
      • CSHARP-5508 — "Revisit Conventions.Apply" (BACKLOG)

            Assignee:
            Ferdinando Papale
            Reporter:
            William Tremblay
            None
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: