# Hibernate ORM — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**

## Finding

Five O(n²) defects in Hibernate ORM's schema mapping layer, all sharing the same root cause: `ArrayList` used as a dedup-tracking container with `contains()` called before `add()` in loops over schema columns, index columns, and FK second-pass queues. All patched. Patches ready for upstream review.

## The Defects

**hibernate-0001 (PATCHED — HIGH):** `mapping/Constraint.java`

```java
// In addColumn() — called per column during schema mapping:
if (!columns.contains(column)) {
    columns.add(column);
}
// columns is ArrayList<Column> — contains() is O(C)
```

O(C²) cost during `SessionFactory` build time. Every unique constraint, primary key, and check constraint accumulates columns through this path.

**hibernate-0002 (PATCHED — HIGH):** `mapping/ForeignKey.java`

```java
// In addReferencedColumn() — per FK column:
if (!referencedColumns.contains(column)) {
    referencedColumns.add(column);
}
// referencedColumns is ArrayList<Column> — contains() is O(C)
```

Same root cause as hibernate-0001 on the FK referenced-column dedup path.

**hibernate-0003 (PATCHED — HIGH):** `mapping/Index.java`

```java
// In addColumn() — per index column:
if (!columns.contains(column)) {
    columns.add(column);
}
// columns is ArrayList<Column> — contains() is O(C)
```

Same root cause as hibernate-0001 on the index column dedup path.

**hibernate-0004 (PATCHED — HIGH):** `boot/model/process/spi/InFlightMetadataCollectorImpl.java`

```java
// In buildRecursiveOrderedFkSecondPasses():
if (!fkSecondPasses.contains(secondPass)) {
    fkSecondPasses.add(0, secondPass);  // O(D) prepend
}
// fkSecondPasses is ArrayList — contains() O(D), add(0,…) O(D)
```

O(D²) over D FK second-passes in inheritance chain processing.

**hibernate-0005 (PATCHED — HIGH):** `engine/internal/StatisticalLoggingSessionEventListener.java`

```java
// In orderHierarchy() — recursive sort:
if (!ordered.contains(type)) {
    ordered.add(type);
}
// ordered is ArrayList — contains() O(T) per type in T-type hierarchy
```

O(T²) over T entity types in the hierarchy ordering sort.

## Complexity Proof

All five defects share the same structure: `ArrayList.contains()` called before `ArrayList.add()` in a loop. For a list of size N built incrementally:
- Element 1: 0 comparisons
- Element 2: 1 comparison
- ...
- Element N: N-1 comparisons
- Total: 0 + 1 + ... + (N-1) = **O(N²)**

At N=5,000 columns: defective=12,497,500 comparisons, fixed=5,000. **19× speedup confirmed by unit test `HibernateConstraintColumnTest`.**

The fix — `LinkedHashSet<Column>` — preserves insertion order (required for correct column ordering in generated DDL) while providing O(1) `contains()`.

## Impact

Hibernate ORM is the dominant Java ORM — used in Spring Boot applications, Jakarta EE, Quarkus, and virtually every Java enterprise application that uses a relational database. `SessionFactory` build time (where these defects activate) runs:

- On every application startup
- On every hot-reload in development (Spring DevTools, Quarkus dev mode)
- On every test suite run that creates an `EntityManagerFactory`
- In AWS Lambda cold starts and Kubernetes pod restarts

Applications with large schemas (many tables, many foreign keys, many constraints) maximize C and hit worst case on every startup. Enterprise applications with 200+ entity classes and complex inheritance hierarchies are common.

## The Fix

Replace `ArrayList` with `LinkedHashSet` throughout (preserves insertion order):

```java
// Before — hibernate-0001/0002/0003
private final List<Column> columns = new ArrayList<>();
if (!columns.contains(column)) {
    columns.add(column);
}

// After
// CWE-407 fix: LinkedHashSet for O(1) contains() with insertion-order preservation.
private final Set<Column> columns = new LinkedHashSet<>();
columns.add(column);  // Set.add() is idempotent — no contains() needed
```

`Column` implements `equals()`/`hashCode()` — no additional changes needed.

## Patch

Fix available: `defects/hibernate/patch/hibernate-0001-0005-column-linkedhashset.patch`

Five-location patch across `Constraint.java`, `ForeignKey.java`, `Index.java`, `InFlightMetadataCollectorImpl.java`, and `StatisticalLoggingSessionEventListener.java`.

Unit test: `HibernateConstraintColumnTest` — **19× speedup at N=5,000 columns**.

## What We Ask

A patch is ready for review.

1. Confirm receipt and assign a Hibernate JIRA reference (hibernate.atlassian.net).
2. Assess severity — all five defects fire on every `SessionFactory` build, which runs at every application startup.
3. Coordinate a disclosure date — we are targeting 90 days from first contact.
4. We will credit the Hibernate team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.
