java-topology/defects/openscad-0002/TICKET.md
russell@unturf.com 597b345da7 openscad: 5-MOAD scan; openscad-0001 CWE-407 AMF vertex dedup 85x, openscad-0002 CWE-407 PolySetBuilder color dedup 69x, openscad-0003 CWE-312 OctoPrint app_token logged
Restructure openscad-0001 (was in wrong dir, Java test) into proper
openscad-0001/ with TICKET.md and Python test. New openscad-0002 patches
PolySetBuilder::endPolygon + appendPolySet std::find on colors_ vector ->
unordered_map; Color4f already has std::hash. New openscad-0003 patches
OctoPrint::requestApiKey and getJsonData to stop logging API responses
verbatim (app_token + api responses exposed under --debug).
MOADs 0002/0003/0005 CLEAN.
2026-04-03 14:10:05 -04:00

1.3 KiB

openscad-0002 — CWE-407 PolySetBuilder color dedup O(F*C) linear scan

MOAD: 0001 (CWE-407 Sedimentary Defect) Severity: MEDIUM Ratio: ~250x at F=1000, C=50 UNDF: (pending)

Location

src/geometry/PolySetBuilder.ccendPolygon() and appendPolySet()

Pattern

PolySetBuilder maintains a std::vector<Color4f> colors_ for per-face color deduplication. Two hot paths scan this vector with std::find:

  1. endPolygon(color) — called once per polygon face. Scans colors_ to find the color index. O(C) per face. Total O(F*C) for F faces with C unique colors.

  2. appendPolySet(ps) — merges colors from another PolySet. Iterates nColors source colors, scanning colors_ for each. O(nC * C).

For a colored model merging 50 source colors into a 1,000-face scene, this performs ~50,000 comparisons per appendPolySet call instead of 50.

Color4f already has std::hash<Color4f> defined in src/geometry/linalg.h. No new infrastructure is needed — just use it.

Fix

Add a parallel std::unordered_map<Color4f, size_t> color_index_ in PolySetBuilder to map each unique color to its index in colors_. Both endPolygon and appendPolySet consult the map instead of scanning the vector. Lookup drops from O(C) to O(1).

Patch

patch/openscad-0002-polysetbuilder-color-dedup.patch