java-topology/defects/efcore/patch/efcore-0001-find-generation-property-hashset.patch
russell@unturf.com d4ed2dff91 ORM wave: 24 defects patched across 10 ORMs (157 sites, 62 ecosystems)
Hibernate (5 HIGH): addColumn/addReferencedColumn/addIndex ArrayList→LinkedHashSet (19x)
  FK second-pass LinkedHashSet, orderHierarchy LinkedHashSet
MyBatis (1 MEDIUM): sortConstructorMappings indexOf→HashMap (12x)
EF Core (2 HIGH + 1 MEDIUM): FindGenerationProperty HashSet (250x),
  AddPrincipals HashSet (250x), FK discovery HashSet (6x)
Diesel (3 MEDIUM): SQLite/MySQL row position()→BTreeMap (51x)
SQLAlchemy (2 HIGH): _values_bindparam Set (500x), evaluated_keys Set (500x)
Peewee (1 MEDIUM): _SortedFieldList.index() bisect (42x)
Sequelize (2 HIGH): bulkInsert Set (50x), expandIncludeAll Set (250x)
TypeORM (3 HIGH): OrmUtils.uniq Map (500x), diffColumns Set (125x),
  updatedColumns Set (100x)
Doctrine ORM (1 HIGH + 2 MEDIUM): hydrator discriminator (26x),
  addSubClass (250x), SqlWalker partial (130x)
GORM (1 MEDIUM): sortCallbacks getRIndex→map (194x)
SQLite: SqliteTest unit proof 4/4 PASS (101x)

Unit tests: all PASS — Hibernate/MyBatis/EfCore/Diesel/SQLAlchemy/Peewee/
  Sequelize/TypeORM/Doctrine/GORM
Whitepaper: 157 sites, 62 ecosystems; PDF 752K
2026-03-27 13:34:26 -04:00

47 lines
2.1 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/src/EFCore/Metadata/Internal/PropertyExtensions.cs b/src/EFCore/Metadata/Internal/PropertyExtensions.cs
index xxxxxxx..xxxxxxx 100644
--- a/src/EFCore/Metadata/Internal/PropertyExtensions.cs
+++ b/src/EFCore/Metadata/Internal/PropertyExtensions.cs
@@ -50,20 +50,23 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal;
public static IProperty? FindGenerationProperty(this IProperty property)
{
- var traversalList = new List<IProperty> { property };
+ // efcore-0001 fix: use HashSet for O(1) visited check in BFS traversal.
+ // Previously List<IProperty>: traversalList.Contains() is O(N) per call,
+ // called inside a while loop over traversalList × foreignKey.Properties loop,
+ // giving O(D²) total cost where D = FK chain depth.
+ // HashSet<IProperty> reduces membership check to O(1), fixing CWE-407.
+ var traversalList = new List<IProperty> { property };
+ var traversalSet = new HashSet<IProperty>(ReferenceEqualityComparer.Instance) { property };
var index = 0;
while (index < traversalList.Count)
{
var currentProperty = traversalList[index];
if (currentProperty.RequiresValueGenerator())
{
return currentProperty;
}
foreach (var foreignKey in currentProperty.GetContainingForeignKeys())
{
for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
{
if (currentProperty == foreignKey.Properties[propertyIndex])
{
var nextProperty = foreignKey.PrincipalKey.Properties[propertyIndex];
- if (!traversalList.Contains(nextProperty))
+ if (traversalSet.Add(nextProperty))
{
traversalList.Add(nextProperty);
}
}
}
}
index++;
}
return null;
}