Skip to content
Permalink
Browse files Browse the repository at this point in the history
Protect against DOS attacks made possible by parsing random invalid e…
…num strings
  • Loading branch information
Brondahl committed Jan 2, 2020
1 parent ef21bf1 commit c0fc780
Showing 1 changed file with 24 additions and 8 deletions.
32 changes: 24 additions & 8 deletions EnumStringValues/EnumExtensions.cs
Expand Up @@ -269,15 +269,12 @@ private static List<StringValueAttribute> GetStringValuesWithPreferences_Uncache
{
var enumTypeObject = typeof(TEnumType);

var typeAppropriateDictionary = parsedEnumStringsDictionaryByType.GetOrAdd(enumTypeObject, (x) => new ConcurrentDictionary<string, Enum>());
var typeAppropriateDictionary = parsedEnumStringsDictionaryByType.GetOrAdd(
enumTypeObject,
(x) => BuildCacheDictionaryForParseStringValue<TEnumType>()
);

var cachedValue = typeAppropriateDictionary.GetOrAdd(lowerStringValue, (str) =>
{
var parseSucceededForDictionary = TryParseStringValueToEnum_Uncached<TEnumType>(lowerStringValue, out var parsedValueForDictionary);
return parseSucceededForDictionary ? (Enum) parsedValueForDictionary : null;
});

if (cachedValue != null)
if (typeAppropriateDictionary.TryGetValue(lowerStringValue, out var cachedValue))
{
parsedValue = (TEnumType)cachedValue;
return true;
Expand All @@ -292,6 +289,25 @@ private static List<StringValueAttribute> GetStringValuesWithPreferences_Uncache
/// <summary> Cache for <see cref="TryParseStringValueToEnum{TEnumType}"/> </summary>
private static ConcurrentDictionary<Type, ConcurrentDictionary<string, Enum>> parsedEnumStringsDictionaryByType;


private static ConcurrentDictionary<string, Enum> BuildCacheDictionaryForParseStringValue<TEnumType>() where TEnumType : System.Enum
{
var dict = new ConcurrentDictionary<string, Enum>();

foreach (var enumValue in EnumerateValues<TEnumType>())
{
foreach (var enumString in GetStringValues<TEnumType>(enumValue))
{
// Add to the dictionary, just overwriting if the string is already present.
// This overwrite is legitimate, because we've declared parsing a duplicate string definition to be `undefined behaviour`.
dict.AddOrUpdate(enumString.ToLower(), enumValue, ((repeatedString, previousEnumValue) => enumValue));
}
}

return dict;
}


private static bool TryParseStringValueToEnum_Uncached<TEnumType>(this string lowerStringValue, out TEnumType parsedValue) where TEnumType : System.Enum
{
foreach (var enumValue in EnumerateValues<TEnumType>())
Expand Down

0 comments on commit c0fc780

Please sign in to comment.