# UNDF: UNDF-2026-000000677
# UNDF: (pending)
# micronaut-0006: GenericUtils.populateTypeArgumentsForInterfaces — O(2^D) diamond re-traversal

## CWE-407 — Algorithmic Complexity: O(2^D) recursive diamond re-traversal

| Field | Value |
|-------|-------|
| ID | micronaut-0006 |
| Severity | MEDIUM |
| Ecosystem | micronaut-core |
| Package | io.micronaut.annotation.processing |
| File | `inject-java/src/main/java/io/micronaut/annotation/processing/GenericUtils.java` |
| Lines | 334–354 |
| Complexity | O(2^D) on diamond interface hierarchies |
| Hot path | Generic type argument resolution — annotation processing at compile time |

## Defect

```java
private void populateTypeArgumentsForInterfaces(
        Map<String, Map<String, TypeMirror>> typeArguments, TypeElement child) {
    for (TypeMirror anInterface : child.getInterfaces()) {
        if (anInterface instanceof DeclaredType declaredType) {
            Element element = declaredType.asElement();
            if (element instanceof TypeElement te) {
                String name = JavaModelUtils.getClassName(te);
                if (!typeArguments.containsKey(name)) {         // containsKey guard...
                    // ... resolves and puts type arguments
                    if (!types.isEmpty()) {
                        typeArguments.put(name, types);
                    }
                }
                populateTypeArgumentsForInterfaces(typeArguments, te); // UNCONDITIONAL → O(2^D)
                // ^ recursion is OUTSIDE the if-block — happens even when
                //   typeArguments.containsKey(name) is true (already processed)
            }
        }
    }
}
```

The `if (!typeArguments.containsKey(name))` guard at line 340 skips the type
argument resolution for already-seen interfaces, but the recursive call at
line 350 is OUTSIDE this guard — it executes unconditionally for every
interface, including those already fully processed.

For a diamond hierarchy `A implements B,C; B extends D; C extends D`, the
call from processing `C` will recurse into `D` even though `D` was already
fully processed when `B` was handled. At depth D, 2^D recursive calls occur.

## Fix

```java
// CORRECT: move recursion inside the guard, or add a separate visited set
private void populateTypeArgumentsForInterfaces(
        Map<String, Map<String, TypeMirror>> typeArguments, TypeElement child) {
    for (TypeMirror anInterface : child.getInterfaces()) {
        if (anInterface instanceof DeclaredType declaredType) {
            Element element = declaredType.asElement();
            if (element instanceof TypeElement te) {
                String name = JavaModelUtils.getClassName(te);
                if (!typeArguments.containsKey(name)) {
                    Map<String, TypeMirror> boundTypes = typeArguments.get(JavaModelUtils.getClassName(child));
                    if (boundTypes == null) {
                        boundTypes = Collections.emptyMap();
                    }
                    Map<String, TypeMirror> types = resolveGenericTypes(declaredType, te, boundTypes);
                    if (!types.isEmpty()) {
                        typeArguments.put(name, types);
                    }
                    populateTypeArgumentsForInterfaces(typeArguments, te); // recurse INSIDE guard
                }
                // If containsKey(name) is true, te was already fully processed — skip recursion
            }
        }
    }
}
```

Alternative: use a separate `Set<TypeElement> visited` passed through the
recursion for O(1) guard instead of relying on map membership.

## Speedup

| Diamond depth (D) | Before (traversals) | After (traversals) | Speedup |
|------------------|--------------------|--------------------|---------|
| 5 | 31 | 5 | 6× |
| 10 | 1,023 | 10 | 102× |
| 15 | 32,767 | 15 | 2,184× |

## Impact

`populateTypeArgumentsForInterfaces` is called during compile-time annotation
processing to resolve generic type parameters across the class hierarchy.
Applications with deep generic interface diamonds (common in repository
patterns, e.g. `Repository<T> extends CrudRepository<T,ID>` shared by
multiple intermediate interfaces) will experience exponential build slowdowns.
