From 91db78cf926939821bc96e8e60616cf5dde0b489 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 24 Oct 2018 15:10:19 -0700 Subject: [PATCH] Add safe copy for enumeration (#1052) --- .../AuthenticationSchemeProvider.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs index c1460851..a7b913b1 100644 --- a/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs +++ b/src/Microsoft.AspNetCore.Authentication.Core/AuthenticationSchemeProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; @@ -49,6 +50,9 @@ protected AuthenticationSchemeProvider(IOptions options, private readonly IDictionary _schemes; private readonly List _requestHandlers; + // Used as a safe return value for enumeration apis + private IEnumerable _schemesCopy = Array.Empty(); + private IEnumerable _requestHandlersCopy = Array.Empty(); private Task GetDefaultSchemeAsync() => _options.DefaultScheme != null @@ -123,7 +127,7 @@ public virtual Task GetSchemeAsync(string name) /// /// The schemes in priority order for request handling public virtual Task> GetRequestHandlerSchemesAsync() - => Task.FromResult>(_requestHandlers); + => Task.FromResult(_requestHandlersCopy); /// /// Registers a scheme for use by . @@ -144,8 +148,10 @@ public virtual void AddScheme(AuthenticationScheme scheme) if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) { _requestHandlers.Add(scheme); + _requestHandlersCopy = _requestHandlers.ToArray(); } _schemes[scheme.Name] = scheme; + _schemesCopy = _schemes.Values.ToArray(); } } @@ -164,13 +170,17 @@ public virtual void RemoveScheme(string name) if (_schemes.ContainsKey(name)) { var scheme = _schemes[name]; - _requestHandlers.Remove(scheme); + if (_requestHandlers.Remove(scheme)) + { + _requestHandlersCopy = _requestHandlers.ToArray(); + } _schemes.Remove(name); + _schemesCopy = _schemes.Values.ToArray(); } } } public virtual Task> GetAllSchemesAsync() - => Task.FromResult>(_schemes.Values); + => Task.FromResult(_schemesCopy); } } \ No newline at end of file