java-topology/whitepaper/outreach/libgdx.md

3.7 KiB
Raw Blame History

libGDX — CWE-407 Disclosure Brief

2026-03-27 · Patch available — awaiting upstream merge

Finding

Four O(n²) defects in libGDX's 3D model loading, reference building, instancing, and font kerning systems. The most severe (libgdx-0004) affects font loading with a 1,971× measured overhead from O(coverage×classes×K) kerning lookups. Patches ready for upstream review.

The Defects

libgdx-0001 (PATCHED — HIGH): Model.java:190

// Inside loadNode() per model node:
// Nested string-ID scan for meshPart and material:
for (ModelMeshPart meshPart : model.meshes) {       // O(meshes)
    for (ModelMeshPart part : node.parts) {         // O(parts)
        if (meshPart.id.equals(part.meshPartId)) {  // O(meshes×parts)

Nested scan to find meshPart and material by string ID per model node. O(parts × (meshes + materials)). Measured ratio: 150×.

libgdx-0002 (PATCHED — MEDIUM): ModelBuilder.java:371

// Inside rebuildReferences():
if (meshParts.contains(part)) { ... }  // Array.contains() ×3

Array.contains() called ×3 during rebuildReferences(). O(parts × materials). Measured ratio: 25×.

libgdx-0003 (PATCHED — MEDIUM): ModelInstance.java

// Inside invalidate() per node-part per model spawn:
if (nodes.contains(node)) { ... }  // Array.contains() per node

Array.contains() scan per node-part during invalidate(). Called on every model instance spawn. O(parts × materials). Measured ratio: 25×.

libgdx-0004 (PATCHED — HIGH): Kerning.java

// Inside GPOS type-2 coverage loop during font load:
if (intArray.contains(glyphId)) { ... }  // IntArray.contains() per glyph

IntArray.contains() O(coverage) scan per glyph class per kerning pair during font loading. For coverage C, classes K, and pairs P: O(coverage × classes × K). Measured ratio: 1,971×.

Complexity Proof

libgdx-0001: 150× measured ratio on models with many mesh parts and materials.

libgdx-0002/0003: 25× measured ratio each — O(parts×materials) per model operation.

libgdx-0004: For C=200 coverage entries, K=100 kerning pairs:

  • Defective: C×K = 20,000 comparisons per font load
  • Fixed: reverse IntIntMap → O(1) per lookup
  • 1,971× measured ratio.

Impact

All libGDX applications loading 3D models (libgdx-0001/0002/0003) and all applications rendering text with OpenType GPOS kerning (libgdx-0004). libGDX is a widely used cross-platform Java game development framework. Games with many 3D assets or rich typography hit these defects on asset load. libgdx-0004 is particularly impactful for UI-heavy games and apps with many font glyphs.

The Fix

libgdx-0001: Pre-build Map<String, ModelMeshPart> and Map<String, ModelMaterial> indexes before the nested loop.

libgdx-0002/0003: Replace Array with ObjectSet for meshParts/nodes dedup collections.

libgdx-0004: Build a reverse IntIntMap<glyphId, classIndex> before the coverage loop:

// Before
if (intArray.contains(glyphId)) { ... }  // O(coverage) per glyph

// After
// CWE-407 fix: IntIntMap for O(1) lookup instead of O(coverage) IntArray scan.
if (glyphToClass.containsKey(glyphId)) { ... }

Patch

defects/libgdx/patch/libgdx-0001-0002-0003-0004-model-kerning-maps.patch

What We Ask

  1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
  2. Validate the patch against your model loading and font rendering test suites.
  3. Assess CVE eligibility — libgdx-0004 measured at 1,971× on font loading.
  4. Coordinate a disclosure date — we are targeting 90 days from first contact.

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