From 4d35c759647ce84ff48935eaaa743daf9ed9fdd0 Mon Sep 17 00:00:00 2001 From: nileshpatil6 Date: Sun, 16 Aug 2026 16:42:21 +0530 Subject: [PATCH] Validate null before mutating CodeNamespaceImportCollection --- .../CodeDom/CodeNamespaceImportCollection.cs | 17 ++++++++-- .../CodeNamespaceImportCollectionTests.cs | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.CodeDom/src/System/CodeDom/CodeNamespaceImportCollection.cs b/src/libraries/System.CodeDom/src/System/CodeDom/CodeNamespaceImportCollection.cs index c55024ac1de8bf..c27477d395e144 100644 --- a/src/libraries/System.CodeDom/src/System/CodeDom/CodeNamespaceImportCollection.cs +++ b/src/libraries/System.CodeDom/src/System/CodeDom/CodeNamespaceImportCollection.cs @@ -16,7 +16,7 @@ public CodeNamespaceImport this[int index] get => (CodeNamespaceImport)_data[index]; set { - _data[index] = value; + _data[index] = Validated(value); SyncKeys(); } } @@ -52,6 +52,17 @@ public void Clear() _keys.Clear(); } + // Add(CodeNamespaceImport) reads value.Namespace before touching _data, so a null + // throws before the collection is modified. The IList members and the indexer setter + // store first, which leaves an element behind that SyncKeys() cannot enumerate. + // Reading Namespace here reproduces that same NullReferenceException at the same + // point, before the store. + private static CodeNamespaceImport Validated(CodeNamespaceImport value) + { + _ = value.Namespace; + return value; + } + private void SyncKeys() { _keys.Clear(); @@ -83,7 +94,7 @@ object IList.this[int index] IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - int IList.Add(object value) => _data.Add((CodeNamespaceImport)value); + int IList.Add(object value) => _data.Add(Validated((CodeNamespaceImport)value)); void IList.Clear() => Clear(); @@ -93,7 +104,7 @@ object IList.this[int index] void IList.Insert(int index, object value) { - _data.Insert(index, (CodeNamespaceImport)value); + _data.Insert(index, Validated((CodeNamespaceImport)value)); SyncKeys(); } diff --git a/src/libraries/System.CodeDom/tests/System/CodeDom/CodeNamespaceImportCollectionTests.cs b/src/libraries/System.CodeDom/tests/System/CodeDom/CodeNamespaceImportCollectionTests.cs index 0ba4c2bf24c8b6..9c3afef69c7b74 100644 --- a/src/libraries/System.CodeDom/tests/System/CodeDom/CodeNamespaceImportCollectionTests.cs +++ b/src/libraries/System.CodeDom/tests/System/CodeDom/CodeNamespaceImportCollectionTests.cs @@ -55,6 +55,40 @@ public void Add_Null_ThrowsNullReferenceException() Assert.Throws(() => collection.Add(null)); } + [Fact] + public void IListAdd_Null_ThrowsNullReferenceExceptionAndLeavesCollectionUsable() + { + IList collection = new CodeNamespaceImportCollection(); + Assert.Throws(() => collection.Add(null)); + + // The failed add must not leave an element behind, otherwise the next + // operation throws while rebuilding the namespace keys. + collection.Insert(0, new CodeNamespaceImport("Namespace")); + Assert.Equal(1, collection.Count); + } + + [Fact] + public void IListInsert_Null_ThrowsNullReferenceExceptionAndLeavesCollectionUsable() + { + IList collection = new CodeNamespaceImportCollection(); + Assert.Throws(() => collection.Insert(0, null)); + + collection.Insert(0, new CodeNamespaceImport("Namespace")); + Assert.Equal(1, collection.Count); + } + + [Fact] + public void ItemSet_Null_ThrowsNullReferenceExceptionAndLeavesCollectionUsable() + { + var collection = new CodeNamespaceImportCollection(); + collection.Add(new CodeNamespaceImport("Namespace")); + + Assert.Throws(() => collection[0] = null); + + Assert.Equal(1, collection.Count); + Assert.Equal("Namespace", collection[0].Namespace); + } + public static IEnumerable AddRange_TestData() { yield return new object[] { new CodeNamespaceImport[0] };