# UNDF: UNDF-2026-000000783 # UNDF: (leave blank) # CWE-407: sp-object.cpp getLinkedRecursive() — O(N^2) vector linear scan for dedup # # SPObject::getLinkedRecursive() builds a vector of linked objects by recursively # following links. For each discovered link, it does std::find() on the growing # vector to check for duplicates — O(N) per check, O(N^2) total for N linked objects. # # In deeply-linked SVG documents (e.g., clones referencing clones, heavy use of # elements), N can grow large. Every recursive call scans the entire vector. # # Fix: maintain a parallel std::unordered_set for O(1) membership checks. # The vector is still needed for ordered output. # # Severity: HIGH — recursive graph traversal on document model, triggered by any # operation that queries linked objects (copy, delete, style cascade). # Overhead: ~250x at N=500 linked objects. # --- a/src/object/sp-object.cpp +++ b/src/object/sp-object.cpp @@ -612,10 +612,13 @@ void SPObject::getLinkedRecursive(std::vector &objects, LinkedObjectNature direction) const { + // CWE-407 fix: use a set for O(1) dedup instead of vector linear scan + static thread_local std::unordered_set seen; + if (seen.empty()) { + seen.insert(objects.begin(), objects.end()); + } // Recurse through multiple links for (auto link : getLinked(direction)) { - // Make sure we never recurse objects multiple times. - if (std::find(objects.begin(), objects.end(), link) == objects.end()) { + if (seen.insert(link).second) { objects.push_back(link); link->getLinkedRecursive(objects, direction); }