Fix DataContractSerializer nullable struct initialization cache lookup - #128506
#128506Merged
StephenMolloy merged 3 commits intoJul 9, 2026
maindotnet/runtime:mainfrom
copilot/fix-datacontractserializer-issuedotnet/runtime:copilot/fix-datacontractserializer-issueCopy head branch name to clipboard
Merged
Fix DataContractSerializer nullable struct initialization cache lookup#128506StephenMolloy merged 3 commits intomaindotnet/runtime:mainfrom copilot/fix-datacontractserializer-issuedotnet/runtime:copilot/fix-datacontractserializer-issueCopy head branch name to clipboard
StephenMolloy merged 3 commits into
maindotnet/runtime:mainfrom
copilot/fix-datacontractserializer-issuedotnet/runtime:copilot/fix-datacontractserializer-issueCopy head branch name to clipboard
Conversation
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/642c45d2-e603-4c5f-a2be-9a512be7b7a0 Co-authored-by: StephenMolloy <19562826+StephenMolloy@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix DataContractSerializer bug with nullable structs in .NET 8
Fix DataContractSerializer nullable struct initialization cache lookup
May 22, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes an incorrect cache-lookup loop in DataContract.GetIdForInitialization(ClassDataContract) that could fail to locate an existing DataContract entry and incorrectly throw SerializationException (DataContract cache overflow) during DataContractSerializer deserialization (notably involving Nullable<T> scenarios).
Changes:
- Corrected the cache scan to index
s_dataContractCacheby the loop variable (i) rather than repeatedly re-checking the originally computedid. - Added a regression test covering nullable root deserialization for a
[DataContract]struct.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs | Fixes the initialization-id lookup to scan the cache correctly by index. |
| src/libraries/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs | Adds regression coverage for nullable root [DataContract] struct handling. |
Co-authored-by: StephenMolloy <19562826+StephenMolloy@users.noreply.github.com>
mangod9
approved these changes
Jul 8, 2026
eiriktsarpalis
pushed a commit
that referenced
this pull request
Jul 15, 2026
#128506) ## Description `DataContractSerializer` regressed in .NET 8+ when deserializing `Nullable<T>` for `[DataContract]` structs that had not been initialized in the cache path yet, causing `SerializationException` (`DataContract cache overflow`). The initialization lookup loop compared against the wrong cache slot, so valid contracts were not found. - ### Runtime fix (`System.Private.DataContractSerialization`) Corrected `DataContract.GetIdForInitialization(ClassDataContract)` to scan cache entries by loop index instead of repeatedly reading the originally computed id. ```csharp for (int i = 0; i < currentDataContractId; i++) { if (ContractMatches(classContract, s_dataContractCache.GetItem(i))) { return i; } } ``` - ### Regression coverage (`System.Runtime.Serialization.Xml` tests) Added `DCS_NullableDataContractStructAsRoot_DeserializesWithoutPriorInitialization`, a cold-cache deserialization test that deserializes a nullable root `[DataContract]` struct from a known XML payload using `ReadObject` only, with no prior `WriteObject` call that could pre-initialize the cache and mask the regression. Fixes #126873 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: StephenMolloy <19562826+StephenMolloy@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
DataContractSerializerregressed in .NET 8+ when deserializingNullable<T>for[DataContract]structs that had not been initialized in the cache path yet, causingSerializationException(DataContract cache overflow).The initialization lookup loop compared against the wrong cache slot, so valid contracts were not found.
Runtime fix (
System.Private.DataContractSerialization)Corrected
DataContract.GetIdForInitialization(ClassDataContract)to scan cache entries by loop index instead of repeatedly reading the originally computed id.Regression coverage (
System.Runtime.Serialization.Xmltests)Added
DCS_NullableDataContractStructAsRoot_DeserializesWithoutPriorInitialization, a cold-cache deserialization test that deserializes a nullable root[DataContract]struct from a known XML payload usingReadObjectonly, with no priorWriteObjectcall that could pre-initialize the cache and mask the regression.Fixes DataContractSerializer bug when serializing nullable structs in .net >= 8.0 #126873