Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 1acb8f4

Browse files
committed
Harden X509Certificate collections
This commit introduces minor behavior changes in order to harden the X509Certificate collections in .NET Core: 1. Using X509CertificateCollection or X509Certificate2Collection as an IList allows adding/inserting non-X509Certificate objects into the collection. Subsequent calls to enumerate or access these items results in InvalidCastException being thrown. This matches the full .NET Framework (desktop) behavior. Clearly this is not the intended behavior of these collections, which are meant to hold X509Certificate and X509Certificate2 objects. This commit changes X509CertificateCollection and X509Certificate2Collection to throw ArgumentException when non-X509Certificate objects are attempted to be added/inserted, via List<X509Certificate>. As part of this, cleanup calling the non-generic IList implementations and null checking. 2. X509CertificateEnumerator has a public constructor with a collection parameter that it uses without first verifying the parameter is non-null, which could result in NullReferenceExceptions. This commit adds a null check, throwing ArgumentNullException if the parameter is null.
1 parent 982d9d1 commit 1acb8f4

File tree

5 files changed

+52
-40
lines changed

5 files changed

+52
-40
lines changed

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,11 @@ public X509Certificate2Collection(X509Certificate2Collection certificates)
3030
{
3131
get
3232
{
33-
return (X509Certificate2)(List[index]);
33+
return (X509Certificate2)(base[index]);
3434
}
3535
set
3636
{
37-
if (value == null)
38-
throw new ArgumentNullException("value");
39-
40-
List[index] = value;
37+
base[index] = value;
4138
}
4239
}
4340

@@ -46,7 +43,7 @@ public int Add(X509Certificate2 certificate)
4643
if (certificate == null)
4744
throw new ArgumentNullException("certificate");
4845

49-
return List.Add(certificate);
46+
return base.Add(certificate);
5047
}
5148

5249
public void AddRange(X509Certificate2[] certificates)
@@ -100,7 +97,7 @@ public bool Contains(X509Certificate2 certificate)
10097
if (certificate == null)
10198
throw new ArgumentNullException("certificate");
10299

103-
return List.Contains(certificate);
100+
return base.Contains(certificate);
104101
}
105102

106103
public byte[] Export(X509ContentType contentType)
@@ -171,15 +168,15 @@ public void Insert(int index, X509Certificate2 certificate)
171168
if (certificate == null)
172169
throw new ArgumentNullException("certificate");
173170

174-
List.Insert(index, certificate);
171+
base.Insert(index, certificate);
175172
}
176173

177174
public void Remove(X509Certificate2 certificate)
178175
{
179176
if (certificate == null)
180177
throw new ArgumentNullException("certificate");
181178

182-
List.Remove(certificate);
179+
base.Remove(certificate);
183180
}
184181

185182
public void RemoveRange(X509Certificate2[] certificates)

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509Certificate2Enumerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace System.Security.Cryptography.X509Certificates
1010
public sealed class X509Certificate2Enumerator : IEnumerator
1111
{
1212
// This is a mutable struct enumerator, so don't mark it as readonly.
13-
private List<object>.Enumerator _enumerator;
13+
private List<X509Certificate>.Enumerator _enumerator;
1414

1515
internal X509Certificate2Enumerator(X509Certificate2Collection collection)
1616
{

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509CertificateCollection.cs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace System.Security.Cryptography.X509Certificates
88
{
99
public partial class X509CertificateCollection : ICollection, IEnumerable, IList
1010
{
11-
private readonly List<object> _list;
11+
private readonly List<X509Certificate> _list;
1212

1313
public X509CertificateCollection()
1414
{
15-
_list = new List<object>();
15+
_list = new List<X509Certificate>();
1616
}
1717

1818
public X509CertificateCollection(X509Certificate[] value)
@@ -39,7 +39,7 @@ bool ICollection.IsSynchronized
3939

4040
object ICollection.SyncRoot
4141
{
42-
get { return ((ICollection)_list).SyncRoot; }
42+
get { return NonGenericList.SyncRoot; }
4343
}
4444

4545
bool IList.IsFixedSize
@@ -56,33 +56,40 @@ object IList.this[int index]
5656
{
5757
get
5858
{
59-
return _list[index];
59+
return NonGenericList[index];
6060
}
6161
set
6262
{
6363
if (value == null)
6464
throw new ArgumentNullException("value");
6565

66-
_list[index] = value;
66+
NonGenericList[index] = value;
6767
}
6868
}
6969

7070
public X509Certificate this[int index]
7171
{
7272
get
7373
{
74-
// Note: If a non-X509Certificate was inserted at this position, the result InvalidCastException is the defined behavior.
75-
return (X509Certificate)(List[index]);
74+
return _list[index];
7675
}
7776
set
7877
{
79-
List[index] = value;
78+
if (value == null)
79+
throw new ArgumentNullException("value");
80+
81+
_list[index] = value;
8082
}
8183
}
8284

8385
public int Add(X509Certificate value)
8486
{
85-
return List.Add(value);
87+
if (value == null)
88+
throw new ArgumentNullException("value");
89+
90+
int index = _list.Count;
91+
_list.Add(value);
92+
return index;
8693
}
8794

8895
public void AddRange(X509Certificate[] value)
@@ -119,7 +126,7 @@ public bool Contains(X509Certificate value)
119126

120127
public void CopyTo(X509Certificate[] array, int index)
121128
{
122-
List.CopyTo(array, index);
129+
_list.CopyTo(array, index);
123130
}
124131

125132
public X509CertificateEnumerator GetEnumerator()
@@ -144,17 +151,23 @@ public override int GetHashCode()
144151

145152
public int IndexOf(X509Certificate value)
146153
{
147-
return List.IndexOf(value);
154+
return _list.IndexOf(value);
148155
}
149156

150157
public void Insert(int index, X509Certificate value)
151158
{
152-
List.Insert(index, value);
159+
if (value == null)
160+
throw new ArgumentNullException("value");
161+
162+
_list.Insert(index, value);
153163
}
154164

155165
public void Remove(X509Certificate value)
156166
{
157-
List.Remove(value);
167+
if (value == null)
168+
throw new ArgumentNullException("value");
169+
170+
_list.Remove(value);
158171
}
159172

160173
public void RemoveAt(int index)
@@ -164,51 +177,49 @@ public void RemoveAt(int index)
164177

165178
void ICollection.CopyTo(Array array, int index)
166179
{
167-
((ICollection)_list).CopyTo(array, index);
180+
NonGenericList.CopyTo(array, index);
168181
}
169182

170183
int IList.Add(object value)
171184
{
172185
if (value == null)
173186
throw new ArgumentNullException("value");
174187

175-
int index = _list.Count;
176-
_list.Add(value);
177-
return index;
188+
return NonGenericList.Add(value);
178189
}
179190

180191
bool IList.Contains(object value)
181192
{
182-
return _list.Contains(value);
193+
return NonGenericList.Contains(value);
183194
}
184195

185196
int IList.IndexOf(object value)
186197
{
187-
return _list.IndexOf(value);
198+
return NonGenericList.IndexOf(value);
188199
}
189200

190201
void IList.Insert(int index, object value)
191202
{
192203
if (value == null)
193204
throw new ArgumentNullException("value");
194205

195-
_list.Insert(index, value);
206+
NonGenericList.Insert(index, value);
196207
}
197208

198209
void IList.Remove(object value)
199210
{
200211
if (value == null)
201212
throw new ArgumentNullException("value");
202213

203-
_list.Remove(value);
214+
NonGenericList.Remove(value);
204215
}
205216

206-
internal IList List
217+
private IList NonGenericList
207218
{
208-
get { return this; }
219+
get { return _list; }
209220
}
210221

211-
internal void GetEnumerator(out List<object>.Enumerator enumerator)
222+
internal void GetEnumerator(out List<X509Certificate>.Enumerator enumerator)
212223
{
213224
enumerator = _list.GetEnumerator();
214225
}

src/System.Security.Cryptography.X509Certificates/src/System/Security/Cryptography/X509Certificates/X509CertificateEnumerator.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ public partial class X509CertificateCollection : ICollection, IEnumerable, IList
1111
public class X509CertificateEnumerator : IEnumerator
1212
{
1313
// This is a mutable struct enumerator, so don't mark it as readonly.
14-
private List<object>.Enumerator _enumerator;
14+
private List<X509Certificate>.Enumerator _enumerator;
1515

1616
public X509CertificateEnumerator(X509CertificateCollection mappings)
1717
{
18+
if (mappings == null)
19+
throw new ArgumentNullException("mappings");
20+
1821
mappings.GetEnumerator(out _enumerator);
1922
}
2023

src/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ public static void X509CertificateCollectionThrowsArgumentNullException()
111111
Assert.Throws<ArgumentNullException>(() => ilist.Insert(0, null));
112112
Assert.Throws<ArgumentNullException>(() => ilist.Remove(null));
113113
}
114+
115+
Assert.Throws<ArgumentNullException>(() => new X509CertificateCollection.X509CertificateEnumerator(null));
114116
}
115117

116118
[Fact]
@@ -273,11 +275,10 @@ public static void X509CertificateCollectionAsIList()
273275
IList il = cc;
274276
Assert.Throws<ArgumentNullException>(() => il[0] = null);
275277

276-
il[0] = "Bogus";
277-
Assert.Equal("Bogus", il[0]);
278-
279-
object ignored;
280-
Assert.Throws<InvalidCastException>(() => ignored = cc[0]);
278+
string bogus = "Bogus";
279+
Assert.Throws<ArgumentException>(() => il[0] = bogus);
280+
Assert.Throws<ArgumentException>(() => il.Add(bogus));
281+
Assert.Throws<ArgumentException>(() => il.Insert(0, bogus));
281282
}
282283
}
283284

0 commit comments

Comments
 (0)