Description
LegacyTagJoiner dynamically calculates its Count property and its GetEnumerator() method iterates over items that could change dynamically during the iteration. This could lead to OOM if not used properly. See reproduction steps.
The same issue exists in ModernTagJoiner as well.
Reproduction Steps
Add and run the following unit test. The memory will start growing and eventually an OOM will be thrown.
[Fact]
public static void OutOfMemoryTest()
{
var joiner = new ExtendedLogger.LegacyTagJoiner { StaticTags = [] };
joiner.SetIncomingTags(
new List<KeyValuePair<string, object?>>
{
new("K1", "V1"),
new("K2", "V2"),
}.AsReadOnly());
var source = joiner.Append(new KeyValuePair<string, object?>("K3", "V3"));
joiner.EnrichmentTagCollector.AddRange(source);
}
When AddRange enumerates source that references the joiner while adding to _extraTags (an inner collection in joiner holding its items), Count increases with each added item --> the enumerator loop never terminates --> unbounded memory growth until OOM.
Expected behavior
OOM shouldn't be thrown, items from the source should be added to the joiner.
Actual behavior
An infinite loop adding items from the source to the joiner causes OOM.
Regression?
No response
Known Workarounds
If you materialize the source by invoking ToArray or ToList the items will be added to the joiner and OOM will not be thrown.
Configuration
No response
Other information
No response
Description
LegacyTagJoinerdynamically calculates itsCountproperty and itsGetEnumerator()method iterates over items that could change dynamically during the iteration. This could lead to OOM if not used properly. See reproduction steps.The same issue exists in
ModernTagJoineras well.Reproduction Steps
Add and run the following unit test. The memory will start growing and eventually an OOM will be thrown.
When
AddRangeenumeratessourcethat references thejoinerwhile adding to_extraTags(an inner collection injoinerholding its items),Countincreases with each added item --> the enumerator loop never terminates --> unbounded memory growth until OOM.Expected behavior
OOM shouldn't be thrown, items from the
sourceshould be added to thejoiner.Actual behavior
An infinite loop adding items from the
sourceto thejoinercauses OOM.Regression?
No response
Known Workarounds
If you materialize the
sourceby invokingToArrayorToListthe items will be added to thejoinerand OOM will not be thrown.Configuration
No response
Other information
No response