Stack overflow in System.Globalization.CompareInfo
Describe the issue Creating a simple azure function produces a stack overflow exception when loading the swagger ui page.
To Reproduce Steps to reproduce the behavior:
- Create a new Azure Function App with a single function.
- Run in the debugger and click the generated Swagger UI page link.
- Swagger UI page fails to load => Stack Overflow Exception
Expected behavior Swagger UI page opens displaying the available function endpoint.
Code
public class ClientsCreate
{
private ECMLDataContext Context { get; set; }
private ILogger<ClientsCreate> Log { get; set; }
public ClientsCreate(ILogger<ClientsCreate> log)
{
//Context = new ECMLDataContext();
Log = log;
}
[OpenApiOperation(nameof(ClientsCreate),
tags: new[] { "Ecml" },
Description = "Creates a new Client record")]
[OpenApiRequestBody(
contentType: "application/json",
bodyType: typeof(Client),
Required = true,
Description = "The body of the request")]
[OpenApiResponseWithBody(
statusCode: HttpStatusCode.OK,
contentType: "application/json",
bodyType: typeof(string),
Description = "Indicates success and returns a user-friendly message")]
[OpenApiResponseWithBody(
HttpStatusCode.BadRequest,
contentType: "application/json",
bodyType: typeof(string),
Description = "Indicates failure and returns a user-friendly message")]
[FunctionName(nameof(ClientsCreate))]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "clients")] HttpRequest req)
{
var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var client = JsonConvert.DeserializeObject<Client>(requestBody);
Context.Clients.Add(client);
await Context.SaveChangesAsync();
return new OkObjectResult(client);
}
}
Environment (please complete the following information, if applicable):
- OS: Windows 11
- Browser Edge
- Version 113.0.1774.35 (Official build) (64-bit)
Call Stack
[Managed to Native Transition]
> System.Private.CoreLib.dll!System.Globalization.CompareInfo.IcuCompareString(System.ReadOnlySpan<char> string1, System.ReadOnlySpan<char> string2, System.Globalization.CompareOptions options) Line 50 C#
System.Private.CoreLib.dll!System.Globalization.CompareInfo.Compare(System.ReadOnlySpan<char> string1, System.ReadOnlySpan<char> string2, System.Globalization.CompareOptions options) Line 448 C#
System.Private.CoreLib.dll!System.Globalization.CompareInfo.Compare(string string1, string string2, System.Globalization.CompareOptions options) Line 300 C#
System.Private.CoreLib.dll!string.Equals(string value, System.StringComparison comparisonType) Line 665 C#
Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.dll!Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions.TypeExtensions.IsArrayType(System.Type type) Unknown
Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.dll!Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.ObjectTypeVisitor.IsVisitable(System.Type type) Unknown
Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.dll!Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.OpenApiSchemaAcceptor.Accept(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.VisitorCollection collection, Newtonsoft.Json.Serialization.NamingStrategy namingStrategy) Unknown
Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.dll!Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.ObjectTypeVisitor.ProcessProperties(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.IOpenApiSchemaAcceptor instance, string schemaName, System.Collections.Generic.Dictionary<string, System.Reflection.PropertyInfo> properties, Newtonsoft.Json.Serialization.NamingStrategy namingStrategy) Unknown
Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.dll!Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.ObjectTypeVisitor.Visit(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions.IAcceptor acceptor, System.Collections.Generic.KeyValuePair<string, System.Type> type, Newtonsoft.Json.Serialization.NamingStrategy namingStrategy, System.Attribute[] attributes) Unknown
Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.dll!Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.OpenApiSchemaAcceptor.Accept(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.VisitorCollection collection, Newtonsoft.Json.Serialization.NamingStrategy namingStrategy) Unknown
Update This error occurs when using the OpenApiRequestBody attribute and specifying a custom object in the bodyType field, and the custom object has a property that references another class whose members include recursive references to the original object class.
[OpenApiRequestBody(
contentType: "application/json",
bodyType: typeof(Client),
Required = true,
Description = "The body of the request")]
In this case, the Client class is declared as follows:
public partial class Client : CommonEntityBase
{
public string? Name { get; set; }
public string? Description { get; set; }
public int ClientId { get; set; }
public virtual Consultant Consultant { get; set; } = null!;
partial void OnCreated();
public Client():base()
{
Name = string.Empty;
Description = string.Empty;
OnCreated();
}
}
Note the reference to the Consultant class, which may contain a collection of Client instances. This is a common one-to-many persistence pattern where a class (in this case Consultant) references a collection of Clients, each of which refers back to the parent instance.
public partial class Consultant : CommonEntityBase
{
/// <summary>Method called from the constructor</summary>
partial void OnCreated();
/// <summary>Initializes a new instance of the <see cref="Consultant"/> class.</summary>
public Consultant() : base()
{
this.Clients = new List<Client>();
this.Company = string.Empty;
this.Name = string.Empty;
this.Title = string.Empty;
OnCreated();
}
/// <summary>Gets or sets the Company field. </summary>
public System.String Company { get; set; }
/// <summary>Gets or sets the Id field. </summary>
public System.Int32 Id { get; set; }
/// <summary>Gets or sets the Name field. </summary>
public System.String Name { get; set; }
/// <summary>Gets or sets the Title field. </summary>
public System.String Title { get; set; }
/// <summary>Represents the navigator which is mapped onto the association 'Consultant.Clients - Client.Consultant (1:n)'</summary>
public virtual List<Client> Clients { get; set; }
/// <summary>Represents the navigator which is mapped onto the association 'Consultant.Profile - UserProfile.Consultant (1:1)'</summary>
public virtual UserProfile Profile { get; set; } = null!;
}
@johnholliday, did you ever get this resolved? Running into something very similar. I have an Azure Functions project. Loads fine and I can execute requests via POSTMAN. The problem occurs when I load Swagger UI:
Stack overflow.
[2023-06-16T12:57:52.251Z] at Interop+Globalization.CompareString(IntPtr, Char*, Int32, Char*, Int32, System.Globalization.CompareOptions)
[2023-06-16T12:57:52.252Z] at System.Globalization.CompareInfo.IcuCompareString(System.ReadOnlySpan`1<Char>, System.ReadOnlySpan`1<Char>, System.Globalization.CompareOptions)
[2023-06-16T12:57:52.255Z] at System.Globalization.CompareInfo.Compare(System.ReadOnlySpan`1<Char>, System.ReadOnlySpan`1<Char>, System.Globalization.CompareOptions)
[2023-06-16T12:57:52.258Z] at System.Globalization.CompareInfo.Compare(System.String, System.String, System.Globalization.CompareOptions)
[2023-06-16T12:57:52.264Z] at System.String.Equals(System.String, System.StringComparison)
[2023-06-16T12:57:52.267Z] at System.Linq.Enumerable+WhereArrayIterator`1[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
[2023-06-16T12:57:52.270Z] at System.Linq.Enumerable.Any[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
[2023-06-16T12:57:52.273Z] at Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Extensions.TypeExtensions.IsArrayType(System.Type)
[2023-06-16T12:57:52.275Z] at Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.OpenApiSchemaAcceptor.Accept(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.VisitorCollection, Newtonsoft.Json.Serialization.NamingStrategy)
[2023-06-16T12:57:52.282Z] at Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.ObjectTypeVisitor.ProcessProperties(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.IOpenApiSchemaAcceptor, System.String, System.Collections.Generic.Dictionary`2<System.String,System.Reflection.PropertyInfo>, Newtonsoft.Json.Serialization.NamingStrategy)
[2023-06-16T12:57:52.285Z] at Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Visitors.ObjectTypeVisitor.Visit(Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions.IAcceptor, System.Collections.Generic.KeyValuePair`2<System.String,System.Type>, Newtonsoft.Json.Serialization.NamingStrategy, System.Attribute[])
The last 3 lines repeat over and over:
- OpenApiSchemaAcceptor.Accept
- ObjectTypeVisitor.ProcessProperties
- ObjectTypeVisitor.Visit
I think that I have the exact same error.