From 070bb0a9dda5a8b7f5841b4ab4265f44ab525d8d Mon Sep 17 00:00:00 2001 From: "Gavin Barron (from Dev Box)" Date: Wed, 19 Aug 2026 08:17:48 -0700 Subject: [PATCH 1/7] fix: harden yaml parsing --- .../performance.Descriptions-report-github.md | 22 +- .../performance.Descriptions-report.csv | 8 +- .../performance.Descriptions-report.html | 22 +- .../performance.Descriptions-report.json | 2 +- .../performance.EmptyModels-report-github.md | 70 ++-- .../performance.EmptyModels-report.csv | 58 +-- .../performance.EmptyModels-report.html | 70 ++-- .../performance.EmptyModels-report.json | 2 +- .../BoundedYamlDocumentParser.cs | 346 ++++++++++++++++++ .../Exceptions/OpenApiReaderException.cs | 2 +- .../InputLimitStream.cs | 151 ++++++++ .../InputLimitTextReader.cs | 123 +++++++ .../Microsoft.OpenApi.Readers.csproj | 2 +- .../OpenApiReaderSettings.cs | 91 ++++- .../OpenApiStreamReader.cs | 50 ++- .../OpenApiTextReaderReader.cs | 37 +- .../OpenApiYamlDocumentReader.cs | 18 +- .../ParseNodes/MapNode.cs | 17 +- .../ParseNodes/ParseNode.cs | 2 +- .../ParseNodes/ValueNode.cs | 8 + .../ParsingContext.cs | 6 +- src/Microsoft.OpenApi.Readers/YamlHelper.cs | 36 +- .../YamlNodeLocationRegistry.cs | 41 +++ .../YamlResourceBudget.cs | 72 ++++ .../Validations/Rules/OpenApiSchemaRules.cs | 102 ++++-- .../Microsoft.OpenApi.Readers.Tests.csproj | 2 +- .../YamlAliasExpansionTests.cs | 10 +- .../YamlResourceLimitTests.cs | 345 +++++++++++++++++ .../Microsoft.OpenApi.Tests.csproj | 2 +- .../OpenApiSchemaValidationTests.cs | 209 +++++++++++ 30 files changed, 1720 insertions(+), 206 deletions(-) create mode 100644 src/Microsoft.OpenApi.Readers/BoundedYamlDocumentParser.cs create mode 100644 src/Microsoft.OpenApi.Readers/InputLimitStream.cs create mode 100644 src/Microsoft.OpenApi.Readers/InputLimitTextReader.cs create mode 100644 src/Microsoft.OpenApi.Readers/YamlNodeLocationRegistry.cs create mode 100644 src/Microsoft.OpenApi.Readers/YamlResourceBudget.cs create mode 100644 test/Microsoft.OpenApi.Readers.Tests/YamlResourceLimitTests.cs diff --git a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md index 240c19d61..06387e1ae 100644 --- a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md +++ b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md @@ -1,18 +1,18 @@ ``` -BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3476) -11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores -.NET SDK 9.0.202 - [Host] : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI - ShortRun : .NET 8.0.14 (8.0.1425.11118), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI +BenchmarkDotNet v0.14.0, Windows 11 (10.0.26200.9106) (Hyper-V) +AMD EPYC 7763, 1 CPU, 16 logical and 8 physical cores +.NET SDK 10.0.303 + [Host] : .NET 8.0.30 (8.0.3026.36720), X64 RyuJIT AVX2 + ShortRun : .NET 8.0.30 (8.0.3026.36720), X64 RyuJIT AVX2 Job=ShortRun IterationCount=3 LaunchCount=1 WarmupCount=3 ``` -| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | -|------------- |---------------:|-------------:|-------------:|-----------:|-----------:|----------:|-------------:| -| PetStoreYaml | 448.7 μs | 326.6 μs | 17.90 μs | 58.5938 | 11.7188 | - | 381.79 KB | -| PetStoreJson | 484.8 μs | 156.9 μs | 8.60 μs | 62.5000 | 15.6250 | - | 389.28 KB | -| GHESYaml | 1,008,349.6 μs | 565,392.0 μs | 30,991.04 μs | 66000.0000 | 23000.0000 | 4000.0000 | 382785 KB | -| GHESJson | 1,039,447.0 μs | 267,501.0 μs | 14,662.63 μs | 67000.0000 | 23000.0000 | 4000.0000 | 389970.77 KB | +| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------- |---------------:|---------------:|--------------:|-----------:|-----------:|----------:|-------------:| +| PetStoreYaml | 941.6 μs | 1,888.8 μs | 103.53 μs | 23.4375 | 7.8125 | - | 440.21 KB | +| PetStoreJson | 984.8 μs | 281.3 μs | 15.42 μs | 25.3906 | 1.9531 | - | 446.38 KB | +| GHESYaml | 2,171,893.7 μs | 478,607.6 μs | 26,234.09 μs | 30000.0000 | 23000.0000 | 4000.0000 | 438630 KB | +| GHESJson | 3,011,015.9 μs | 7,499,811.5 μs | 411,089.98 μs | 30000.0000 | 23000.0000 | 4000.0000 | 445811.67 KB | diff --git a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv index 0cf62d174..1b90a79f0 100644 --- a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv +++ b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv @@ -1,5 +1,5 @@ Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated -PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,448.7 μs,326.6 μs,17.90 μs,58.5938,11.7188,0.0000,381.79 KB -PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,484.8 μs,156.9 μs,8.60 μs,62.5000,15.6250,0.0000,389.28 KB -GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"1,008,349.6 μs","565,392.0 μs","30,991.04 μs",66000.0000,23000.0000,4000.0000,382785 KB -GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"1,039,447.0 μs","267,501.0 μs","14,662.63 μs",67000.0000,23000.0000,4000.0000,389970.77 KB +PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,941.6 μs,"1,888.8 μs",103.53 μs,23.4375,7.8125,0.0000,440.21 KB +PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,984.8 μs,281.3 μs,15.42 μs,25.3906,1.9531,0.0000,446.38 KB +GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"2,171,893.7 μs","478,607.6 μs","26,234.09 μs",30000.0000,23000.0000,4000.0000,438630 KB +GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"3,011,015.9 μs","7,499,811.5 μs","411,089.98 μs",30000.0000,23000.0000,4000.0000,445811.67 KB diff --git a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html index 0aef47715..2c6f9a523 100644 --- a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html +++ b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html @@ -2,7 +2,7 @@ -performance.Descriptions-20250408-125836 +performance.Descriptions-20260818-205302