diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs index 1860699f3bd96..46fa51b60e9c4 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs @@ -67,9 +67,17 @@ internal void Load(IDictionary envVariables) { prefix = CustomPrefix; } + else if (key.StartsWith(_prefix, StringComparison.OrdinalIgnoreCase)) + { + // This prevents the prefix from being normalized. + // We can also do a fast path branch, I guess? No point in reallocating if the prefix is empty. + key = NormalizeKey(key.Substring(_prefix.Length)); + data[key] = entry.Value as string; + + continue; + } else { - AddIfPrefixed(data, NormalizeKey(key), (string)entry.Value); continue; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs index 533a93fa83b54..d23fe8faf3d1a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs @@ -143,14 +143,72 @@ public void ReplaceDoubleUnderscoreInEnvironmentVariables() var dict = new Hashtable() { {"data__ConnectionString", "connection"}, - {"SQLCONNSTR__db1", "connStr"} + {"SQLCONNSTR_db1", "connStr"} }; var envConfigSrc = new EnvironmentVariablesConfigurationProvider(); envConfigSrc.Load(dict); Assert.Equal("connection", envConfigSrc.Get("data:ConnectionString")); - Assert.Equal("System.Data.SqlClient", envConfigSrc.Get("ConnectionStrings:_db1_ProviderName")); + Assert.Equal("System.Data.SqlClient", envConfigSrc.Get("ConnectionStrings:db1_ProviderName")); + } + + [Fact] + public void ReplaceDoubleUnderscoreInEnvironmentVariablesButNotPrefix() + { + var dict = new Hashtable() + { + {"test__prefix__with__double__underscores__data__ConnectionString", "connection"} + }; + var envConfigSrc = new EnvironmentVariablesConfigurationProvider("test__prefix__with__double__underscores__"); + + envConfigSrc.Load(dict); + + Assert.Equal("connection", envConfigSrc.Get("data:ConnectionString")); + } + + [Fact] + public void ReplaceDoubleUnderscoreInEnvironmentVariablesButNotInAnomalousPrefix() + { + var dict = new Hashtable() + { + {"_____EXPERIMENTAL__data__ConnectionString", "connection"} + }; + var envConfigSrc = new EnvironmentVariablesConfigurationProvider("_____EXPERIMENTAL__"); + + envConfigSrc.Load(dict); + + Assert.Equal("connection", envConfigSrc.Get("data:ConnectionString")); + } + + [Fact] + public void ReplaceDoubleUnderscoreInEnvironmentVariablesWithDuplicatedPrefix() + { + var dict = new Hashtable() + { + {"test__test__ConnectionString", "connection"} + }; + var envConfigSrc = new EnvironmentVariablesConfigurationProvider("test__"); + + envConfigSrc.Load(dict); + + Assert.Equal("connection", envConfigSrc.Get("test:ConnectionString")); + } + + [Fact] + public void PrefixPreventsLoadingSqlConnectionStrings() + { + var dict = new Hashtable() + { + {"test__test__ConnectionString", "connection"}, + {"SQLCONNSTR_db1", "connStr"} + }; + var envConfigSrc = new EnvironmentVariablesConfigurationProvider("test__"); + + envConfigSrc.Load(dict); + + Assert.Equal("connection", envConfigSrc.Get("test:ConnectionString")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:db1_ProviderName")); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]