51 lines
2.1 KiB
Diff
51 lines
2.1 KiB
Diff
# UNDF: UNDF-2026-000000140
|
||
Fixes libgdx-0004: Kerning.java — O(C×N×G) IntArray.contains() in GPOS coverage loop
|
||
replaced with IntIntMap for O(1) glyph→class lookup.
|
||
|
||
--- a/extensions/gdx-tools/src/com/badlogic/gdx/tools/hiero/Kerning.java
|
||
+++ b/extensions/gdx-tools/src/com/badlogic/gdx/tools/hiero/Kerning.java
|
||
|
||
@@ DEFECT libgdx-0004: GPOS type-2 coverage loop — IntArray.contains() inside
|
||
@@ double loop: O(coverage × class1Count × avg_glyphs_per_class)
|
||
|
||
+import com.badlogic.gdx.utils.IntIntMap;
|
||
|
||
// In the GPOS subtype 2 handler (readSubtable2 or equivalent):
|
||
IntArray[] glyphsByClass1 = readClassDefinition(subTablePosition + classDefOffset1, class1Count);
|
||
IntArray[] glyphsByClass2 = readClassDefinition(subTablePosition + classDefOffset2, class2Count);
|
||
input.seek(position);
|
||
|
||
+ // FIX libgdx-0004: build reverse map glyph→class1 index once in O(G) total
|
||
+ IntIntMap glyphToClass1 = new IntIntMap(glyphsByClass1.length * 16);
|
||
+ for (int c = 1; c < class1Count; c++) {
|
||
+ IntArray classGlyphs = glyphsByClass1[c];
|
||
+ for (int k = 0; k < classGlyphs.size; k++) {
|
||
+ glyphToClass1.put(classGlyphs.items[k], c);
|
||
+ }
|
||
+ }
|
||
|
||
- // DEFECT: O(C × class1Count × avg_K) — CWE-407
|
||
- for (int i = 0; i < coverage.length; i++) {
|
||
- int glyph = coverage[i];
|
||
- boolean found = false;
|
||
- for (int j = 1; j < class1Count && !found; j++) {
|
||
- found = glyphsByClass1[j].contains(glyph); // O(K) per class
|
||
- }
|
||
- if (!found) {
|
||
- glyphsByClass1[0].add(glyph);
|
||
- }
|
||
- }
|
||
|
||
+ // FIX libgdx-0004: O(C) — one map lookup per covered glyph
|
||
+ for (int i = 0; i < coverage.length; i++) {
|
||
+ int glyph = coverage[i];
|
||
+ if (!glyphToClass1.containsKey(glyph)) { // O(1)
|
||
+ glyphsByClass1[0].add(glyph);
|
||
+ // no need to add to map — class 0 is the "unclassified" fallback
|
||
+ }
|
||
+ }
|
||
|
||
// Remainder of pair-adjustment loop unchanged
|
||
for (int i = 0; i < class1Count; i++) {
|
||
for (int j = 0; j < class2Count; j++) { ... }
|
||
}
|