Skip to content

Commit c0fc780

Browse files
committed
Protect against DOS attacks made possible by parsing random invalid enum strings
1 parent ef21bf1 commit c0fc780

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

Diff for: EnumStringValues/EnumExtensions.cs

+24-8
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,12 @@ private static bool TryParseStringValueToEnum_ViaCache<TEnumType>(string lowerSt
269269
{
270270
var enumTypeObject = typeof(TEnumType);
271271

272-
var typeAppropriateDictionary = parsedEnumStringsDictionaryByType.GetOrAdd(enumTypeObject, (x) => new ConcurrentDictionary<string, Enum>());
272+
var typeAppropriateDictionary = parsedEnumStringsDictionaryByType.GetOrAdd(
273+
enumTypeObject,
274+
(x) => BuildCacheDictionaryForParseStringValue<TEnumType>()
275+
);
273276

274-
var cachedValue = typeAppropriateDictionary.GetOrAdd(lowerStringValue, (str) =>
275-
{
276-
var parseSucceededForDictionary = TryParseStringValueToEnum_Uncached<TEnumType>(lowerStringValue, out var parsedValueForDictionary);
277-
return parseSucceededForDictionary ? (Enum) parsedValueForDictionary : null;
278-
});
279-
280-
if (cachedValue != null)
277+
if (typeAppropriateDictionary.TryGetValue(lowerStringValue, out var cachedValue))
281278
{
282279
parsedValue = (TEnumType)cachedValue;
283280
return true;
@@ -292,6 +289,25 @@ private static bool TryParseStringValueToEnum_ViaCache<TEnumType>(string lowerSt
292289
/// <summary> Cache for <see cref="TryParseStringValueToEnum{TEnumType}"/> </summary>
293290
private static ConcurrentDictionary<Type, ConcurrentDictionary<string, Enum>> parsedEnumStringsDictionaryByType;
294291

292+
293+
private static ConcurrentDictionary<string, Enum> BuildCacheDictionaryForParseStringValue<TEnumType>() where TEnumType : System.Enum
294+
{
295+
var dict = new ConcurrentDictionary<string, Enum>();
296+
297+
foreach (var enumValue in EnumerateValues<TEnumType>())
298+
{
299+
foreach (var enumString in GetStringValues<TEnumType>(enumValue))
300+
{
301+
// Add to the dictionary, just overwriting if the string is already present.
302+
// This overwrite is legitimate, because we've declared parsing a duplicate string definition to be `undefined behaviour`.
303+
dict.AddOrUpdate(enumString.ToLower(), enumValue, ((repeatedString, previousEnumValue) => enumValue));
304+
}
305+
}
306+
307+
return dict;
308+
}
309+
310+
295311
private static bool TryParseStringValueToEnum_Uncached<TEnumType>(this string lowerStringValue, out TEnumType parsedValue) where TEnumType : System.Enum
296312
{
297313
foreach (var enumValue in EnumerateValues<TEnumType>())

0 commit comments

Comments
 (0)