java-topology/whitepaper/outreach/musescore-0001.md
russell@unturf.com 652608142a feat: close outreach doc gap — 276 docs (batches 11-16)
All projects with patches now have outreach docs. 276 new docs covering
CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#,
PHP, Ruby, JavaScript, Dart, Erlang, R, and more.

Outreach gap: 276 -> 0.
2026-04-15 13:57:42 -04:00

2.5 KiB
Raw Permalink Blame History

MuseScore — CWE-407 Disclosure Brief (musescore-0001)

2026-04-13 · Patch available — awaiting upstream merge

Finding

One O(n²) defect in MuseScore's paste-staff harmony deduplication. Patched. Three file format reader versions (Read400, Read410, Read460) use std::find() on a vector<Harmony*> for dedup during paste operations.

The Defect

musescore-0001 (PATCHED — MEDIUM): src/engraving/rw/read400/read400.cpp:625 (and read410, read460)

// In pasteStaff() — fires per pasted harmony element:
std::vector<Harmony*> pastedHarmony;
// ...
for (EngravingItem* el : seg->findAnnotations(...)) {
    if (std::find(pastedHarmony.begin(), pastedHarmony.end(), el) == pastedHarmony.end()) {
        score->undoRemoveElement(el);
    }
}
// ...
pastedHarmony.push_back(harmony);

pastedHarmony is vector<Harmony*>. std::find() is O(N) per lookup. For each pasted harmony, existing harmonies are checked against the growing list. With H harmonies pasted, total cost: O(H²).

Complexity Proof

At H=200 harmonies (large orchestral paste):

  • Defective: 200 × 100 avg = 20,000 pointer comparisons
  • Fixed: 200 × O(1) unordered_set lookups = 200 operations
  • 100× op reduction at 200 harmonies.

Impact

MuseScore is the world's most popular open-source music notation software. Paste operations on large orchestral scores with many chord symbols/harmonies trigger quadratic dedup. The defect appears in three file format readers (400, 410, 460), affecting all supported score formats.

The Fix

Replace std::vector<Harmony*> with std::unordered_set<Harmony*>:

// Before
std::vector<Harmony*> pastedHarmony;
std::find(pastedHarmony.begin(), pastedHarmony.end(), el)  // O(N)

// After
std::unordered_set<Harmony*> pastedHarmony;
pastedHarmony.find(static_cast<Harmony*>(el))              // O(1)

Patch

Fix available: defects/musescore-0001/patch/musescore-0001.patch

Touches read400.cpp, read410.cpp, and read460.cpp. Same fix applied to all three format readers. 100× speedup at 200 harmonies.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (musescore/MuseScore).
  2. Assess severity — fires during paste operations on scores with many harmonies.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the MuseScore team in the public disclosure. Preferred acknowledgment format welcome.

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